Mercurial > 510Connectbot
comparison src/net/sourceforge/jsocks/Socks5Proxy.java @ 349:205ee2873330
update jsocks to 2011-03-19
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 01 Aug 2014 11:23:10 -0700 |
parents | 0ce5cc452d02 |
children |
comparison
equal
deleted
inserted
replaced
348:29076621bab0 | 349:205ee2873330 |
---|---|
1 package net.sourceforge.jsocks; | 1 package net.sourceforge.jsocks; |
2 import java.io.IOException; | 2 import java.net.*; |
3 import java.io.InputStream; | 3 import java.io.*; |
4 import java.io.OutputStream; | 4 import java.util.Hashtable; |
5 import java.net.InetAddress; | |
6 import java.net.Socket; | |
7 import java.net.SocketException; | |
8 import java.net.UnknownHostException; | |
9 import java.util.Enumeration; | 5 import java.util.Enumeration; |
10 import java.util.Hashtable; | |
11 | 6 |
12 /** | 7 /** |
13 SOCKS5 Proxy. | 8 SOCKS5 CProxy. |
14 */ | 9 */ |
15 | 10 |
16 public class Socks5Proxy extends Proxy implements Cloneable { | 11 public class Socks5Proxy extends CProxy implements Cloneable{ |
17 | 12 |
18 //Data members | 13 //Data members |
19 private Hashtable<Integer, Authentication> authMethods = new Hashtable<Integer, Authentication>(); | 14 private Hashtable authMethods = new Hashtable(); |
20 private int selectedMethod; | 15 private int selectedMethod; |
21 | 16 |
22 boolean resolveAddrLocally = true; | 17 boolean resolveAddrLocally = true; |
23 UDPEncapsulation udp_encapsulation = null; | 18 UDPEncapsulation udp_encapsulation=null; |
24 | 19 |
25 | 20 |
26 //Public Constructors | 21 //Public Constructors |
27 //==================== | 22 //==================== |
28 | 23 |
29 /** | 24 /** |
30 Creates SOCKS5 proxy. | 25 Creates SOCKS5 proxy. |
31 @param proxyHost Host on which a Proxy server runs. | 26 @param p CProxy to use to connect to this proxy, allows proxy chaining. |
32 @param proxyPort Port on which a Proxy server listens for connections. | 27 @param proxyHost Host on which a CProxy server runs. |
33 @throws UnknownHostException If proxyHost can't be resolved. | 28 @param proxyPort Port on which a CProxy server listens for connections. |
34 */ | 29 @throws UnknownHostException If proxyHost can't be resolved. |
35 public Socks5Proxy(String proxyHost, int proxyPort) | 30 */ |
36 throws UnknownHostException { | 31 public Socks5Proxy(CProxy p,String proxyHost,int proxyPort) |
37 super(proxyHost, proxyPort); | 32 throws UnknownHostException{ |
38 version = 5; | 33 super(p,proxyHost,proxyPort); |
39 setAuthenticationMethod(0, new AuthenticationNone()); | 34 version = 5; |
40 } | 35 setAuthenticationMethod(0,new AuthenticationNone()); |
41 | 36 } |
42 | 37 |
43 /** | 38 /** |
44 Creates SOCKS5 proxy. | 39 Creates SOCKS5 proxy. |
45 @param proxyIP Host on which a Proxy server runs. | 40 @param proxyHost Host on which a CProxy server runs. |
46 @param proxyPort Port on which a Proxy server listens for connections. | 41 @param proxyPort Port on which a CProxy server listens for connections. |
47 */ | 42 @throws UnknownHostException If proxyHost can't be resolved. |
48 public Socks5Proxy(InetAddress proxyIP, int proxyPort) { | 43 */ |
49 super(proxyIP, proxyPort); | 44 public Socks5Proxy(String proxyHost,int proxyPort) |
50 version = 5; | 45 throws UnknownHostException{ |
51 setAuthenticationMethod(0, new AuthenticationNone()); | 46 this(null,proxyHost,proxyPort); |
52 } | 47 } |
53 | 48 |
49 | |
50 /** | |
51 Creates SOCKS5 proxy. | |
52 @param p CProxy to use to connect to this proxy, allows proxy chaining. | |
53 @param proxyIP Host on which a CProxy server runs. | |
54 @param proxyPort Port on which a CProxy server listens for connections. | |
55 */ | |
56 public Socks5Proxy(CProxy p,InetAddress proxyIP,int proxyPort){ | |
57 super(p,proxyIP,proxyPort); | |
58 version = 5; | |
59 setAuthenticationMethod(0,new AuthenticationNone()); | |
60 } | |
61 | |
62 /** | |
63 Creates SOCKS5 proxy. | |
64 @param proxyIP Host on which a CProxy server runs. | |
65 @param proxyPort Port on which a CProxy server listens for connections. | |
66 */ | |
67 public Socks5Proxy(InetAddress proxyIP,int proxyPort){ | |
68 this(null,proxyIP,proxyPort); | |
69 } | |
54 | 70 |
55 //Public instance methods | 71 //Public instance methods |
56 //======================== | 72 //======================== |
57 | 73 |
58 | 74 |
59 /** | 75 /** |
60 * Wether to resolve address locally or to let proxy do so. | 76 * Wether to resolve address locally or to let proxy do so. |
61 <p> | 77 <p> |
62 SOCKS5 protocol allows to send host names rather then IPs in the | 78 SOCKS5 protocol allows to send host names rather then IPs in the |
63 requests, this option controls wether the hostnames should be send | 79 requests, this option controls wether the hostnames should be send |
64 to the proxy server as names, or should they be resolved locally. | 80 to the proxy server as names, or should they be resolved locally. |
65 @param doResolve Wether to perform resolution locally. | 81 @param doResolve Wether to perform resolution locally. |
66 @return Previous settings. | 82 @return Previous settings. |
67 */ | |
68 public boolean resolveAddrLocally(boolean doResolve) { | |
69 boolean old = resolveAddrLocally; | |
70 resolveAddrLocally = doResolve; | |
71 return old; | |
72 } | |
73 /** | |
74 Get current setting on how the addresses should be handled. | |
75 @return Current setting for address resolution. | |
76 @see Socks5Proxy#resolveAddrLocally(boolean doResolve) | |
77 */ | 83 */ |
78 public boolean resolveAddrLocally() { | 84 public boolean resolveAddrLocally(boolean doResolve){ |
79 return resolveAddrLocally; | 85 boolean old = resolveAddrLocally; |
80 } | 86 resolveAddrLocally = doResolve; |
81 | 87 return old; |
82 /** | 88 } |
83 Adds another authentication method. | 89 /** |
84 @param methodId Authentication method id, see rfc1928 | 90 Get current setting on how the addresses should be handled. |
85 @param method Implementation of Authentication | 91 @return Current setting for address resolution. |
86 @see Authentication | 92 @see Socks5Proxy#resolveAddrLocally(boolean doResolve) |
87 */ | 93 */ |
88 public boolean setAuthenticationMethod(int methodId, | 94 public boolean resolveAddrLocally(){ |
89 Authentication method) { | 95 return resolveAddrLocally; |
90 if (methodId < 0 || methodId > 255) | 96 } |
91 return false; | 97 |
92 | 98 /** |
93 if (method == null) { | 99 Adds another authentication method. |
94 //Want to remove a particular method | 100 @param methodId Authentication method id, see rfc1928 |
95 return (authMethods.remove(Integer.valueOf(methodId)) != null); | 101 @param method Implementation of Authentication |
96 } | 102 @see Authentication |
97 else {//Add the method, or rewrite old one | 103 */ |
98 authMethods.put(Integer.valueOf(methodId), method); | 104 public boolean setAuthenticationMethod(int methodId, |
99 } | 105 Authentication method){ |
100 | 106 if(methodId<0 || methodId > 255) |
101 return true; | 107 return false; |
102 } | 108 if(method == null){ |
103 | 109 //Want to remove a particular method |
104 /** | 110 return (authMethods.remove(new Integer(methodId)) != null); |
105 Get authentication method, which corresponds to given method id | 111 }else{//Add the method, or rewrite old one |
106 @param methodId Authentication method id. | 112 authMethods.put(new Integer(methodId),method); |
107 @return Implementation for given method or null, if one was not set. | 113 } |
108 */ | 114 return true; |
109 public Authentication getAuthenticationMethod(int methodId) { | 115 } |
110 Object method = authMethods.get(Integer.valueOf(methodId)); | 116 |
111 | 117 /** |
112 if (method == null) return null; | 118 Get authentication method, which corresponds to given method id |
113 | 119 @param methodId Authentication method id. |
114 return (Authentication)method; | 120 @return Implementation for given method or null, if one was not set. |
115 } | 121 */ |
116 | 122 public Authentication getAuthenticationMethod(int methodId){ |
117 /** | 123 Object method = authMethods.get(new Integer(methodId)); |
118 Creates a clone of this Proxy. | 124 if(method == null) return null; |
119 */ | 125 return (Authentication)method; |
120 @Override | 126 } |
121 @SuppressWarnings("unchecked") | 127 |
122 public Object clone() { | 128 /** |
123 Socks5Proxy newProxy = new Socks5Proxy(proxyIP, proxyPort); | 129 Creates a clone of this CProxy. |
124 newProxy.authMethods = (Hashtable<Integer, Authentication>) this.authMethods.clone(); | 130 */ |
125 newProxy.resolveAddrLocally = resolveAddrLocally; | 131 public Object clone(){ |
126 newProxy.chainProxy = chainProxy; | 132 Socks5Proxy newProxy = new Socks5Proxy(proxyIP,proxyPort); |
127 return newProxy; | 133 newProxy.authMethods = (Hashtable) this.authMethods.clone(); |
128 } | 134 newProxy.directHosts = (InetRange)directHosts.clone(); |
135 newProxy.resolveAddrLocally = resolveAddrLocally; | |
136 newProxy.chainProxy = chainProxy; | |
137 return newProxy; | |
138 } | |
129 | 139 |
130 //Public Static(Class) Methods | 140 //Public Static(Class) Methods |
131 //============================== | 141 //============================== |
132 | 142 |
133 | 143 |
134 //Protected Methods | 144 //Protected Methods |
135 //================= | 145 //================= |
136 | 146 |
137 @Override | 147 protected CProxy copy(){ |
138 protected Proxy copy() { | 148 Socks5Proxy copy = new Socks5Proxy(proxyIP,proxyPort); |
139 Socks5Proxy copy = new Socks5Proxy(proxyIP, proxyPort); | 149 copy.authMethods = this.authMethods; //same Hash, no copy |
140 copy.authMethods = this.authMethods; //same Hash, no copy | 150 copy.directHosts = this.directHosts; |
141 copy.chainProxy = this.chainProxy; | 151 copy.chainProxy = this.chainProxy; |
142 copy.resolveAddrLocally = this.resolveAddrLocally; | 152 copy.resolveAddrLocally = this.resolveAddrLocally; |
143 return copy; | 153 return copy; |
144 } | 154 } |
145 /** | 155 /** |
146 * | 156 * |
147 * | 157 * |
148 */ | 158 */ |
149 @Override | 159 protected void startSession()throws SocksException{ |
150 protected void startSession()throws SocksException { | 160 super.startSession(); |
151 super.startSession(); | 161 Authentication auth; |
152 Authentication auth; | 162 Socket ps = proxySocket; //The name is too long |
153 Socket ps = proxySocket; //The name is too long | 163 |
154 | 164 try{ |
155 try { | 165 |
156 byte nMethods = (byte) authMethods.size(); //Number of methods | 166 byte nMethods = (byte) authMethods.size(); //Number of methods |
157 byte[] buf = new byte[2 + nMethods]; //2 is for VER,NMETHODS | 167 |
158 buf[0] = (byte) version; | 168 byte[] buf = new byte[2+nMethods]; //2 is for VER,NMETHODS |
159 buf[1] = nMethods; //Number of methods | 169 buf[0] = (byte) version; |
160 int i = 2; | 170 buf[1] = nMethods; //Number of methods |
161 Enumeration<Integer> ids = authMethods.keys(); | 171 int i=2; |
162 | 172 |
163 while (ids.hasMoreElements()) | 173 Enumeration ids = authMethods.keys(); |
164 buf[i++] = (byte)ids.nextElement().intValue(); | 174 while(ids.hasMoreElements()) |
165 | 175 buf[i++] = (byte)((Integer)ids.nextElement()).intValue(); |
166 out.write(buf); | 176 |
167 out.flush(); | 177 out.write(buf); |
168 int versionNumber = in.read(); | 178 out.flush(); |
169 selectedMethod = in.read(); | 179 |
170 | 180 int versionNumber = in.read(); |
171 if (versionNumber < 0 || selectedMethod < 0) { | 181 selectedMethod = in.read(); |
172 //EOF condition was reached | 182 |
173 endSession(); | 183 if(versionNumber < 0 || selectedMethod < 0){ |
174 throw(new SocksException(SOCKS_PROXY_IO_ERROR, | 184 //EOF condition was reached |
175 "Connection to proxy lost.")); | 185 endSession(); |
176 } | 186 throw(new SocksException(SOCKS_PROXY_IO_ERROR, |
177 | 187 "Connection to proxy lost.")); |
178 if (versionNumber < version) { | 188 } |
179 //What should we do?? | 189 if(versionNumber < version){ |
180 } | 190 //What should we do?? |
181 | 191 } |
182 if (selectedMethod == 0xFF) { //No method selected | 192 if(selectedMethod == 0xFF){ //No method selected |
183 ps.close(); | 193 ps.close(); |
184 throw(new SocksException(SOCKS_AUTH_NOT_SUPPORTED)); | 194 throw ( new SocksException(SOCKS_AUTH_NOT_SUPPORTED)); |
185 } | 195 } |
186 | 196 |
187 auth = getAuthenticationMethod(selectedMethod); | 197 auth = getAuthenticationMethod(selectedMethod); |
188 | 198 if(auth == null){ |
189 if (auth == null) { | 199 //This shouldn't happen, unless method was removed by other |
190 //This shouldn't happen, unless method was removed by other | 200 //thread, or the server stuffed up |
191 //thread, or the server stuffed up | 201 throw(new SocksException(SOCKS_JUST_ERROR, |
192 throw(new SocksException(SOCKS_JUST_ERROR, | 202 "Speciefied Authentication not found!")); |
193 "Speciefied Authentication not found!")); | 203 } |
194 } | 204 Object[] in_out = auth.doSocksAuthentication(selectedMethod,ps); |
195 | 205 if(in_out == null){ |
196 Object[] in_out = auth.doSocksAuthentication(selectedMethod, ps); | 206 //Authentication failed by some reason |
197 | 207 throw(new SocksException(SOCKS_AUTH_FAILURE)); |
198 if (in_out == null) { | 208 } |
199 //Authentication failed by some reason | 209 //Most authentication methods are expected to return |
200 throw(new SocksException(SOCKS_AUTH_FAILURE)); | 210 //simply the input/output streams associated with |
201 } | 211 //the socket. However if the auth. method requires |
202 | 212 //some kind of encryption/decryption being done on the |
203 //Most authentication methods are expected to return | 213 //connection it should provide classes to handle I/O. |
204 //simply the input/output streams associated with | 214 |
205 //the socket. However if the auth. method requires | 215 in = (InputStream) in_out[0]; |
206 //some kind of encryption/decryption being done on the | 216 out = (OutputStream) in_out[1]; |
207 //connection it should provide classes to handle I/O. | 217 if(in_out.length > 2) |
208 in = (InputStream) in_out[0]; | 218 udp_encapsulation = (UDPEncapsulation) in_out[2]; |
209 out = (OutputStream) in_out[1]; | 219 |
210 | 220 }catch(SocksException s_ex){ |
211 if (in_out.length > 2) | 221 throw s_ex; |
212 udp_encapsulation = (UDPEncapsulation) in_out[2]; | 222 }catch(UnknownHostException uh_ex){ |
213 } | 223 throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); |
214 catch (SocksException s_ex) { | 224 }catch(SocketException so_ex){ |
215 throw s_ex; | 225 throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); |
216 } | 226 }catch(IOException io_ex){ |
217 catch (UnknownHostException uh_ex) { | 227 //System.err.println(io_ex); |
218 throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); | 228 throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex)); |
219 } | 229 } |
220 catch (SocketException so_ex) { | 230 } |
221 throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); | 231 |
222 } | 232 protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){ |
223 catch (IOException io_ex) { | 233 return new Socks5Message(cmd,ip,port); |
224 //System.err.println(io_ex); | 234 } |
225 throw(new SocksException(SOCKS_PROXY_IO_ERROR, "" + io_ex)); | 235 protected ProxyMessage formMessage(int cmd,String host,int port) |
226 } | 236 throws UnknownHostException{ |
227 } | 237 if(resolveAddrLocally) |
228 | 238 return formMessage(cmd,InetAddress.getByName(host),port); |
229 @Override | 239 else |
230 protected ProxyMessage formMessage(int cmd, InetAddress ip, int port) { | 240 return new Socks5Message(cmd,host,port); |
231 return new Socks5Message(cmd, ip, port); | 241 } |
232 } | 242 protected ProxyMessage formMessage(InputStream in) |
233 @Override | 243 throws SocksException, |
234 protected ProxyMessage formMessage(int cmd, String host, int port) | 244 IOException{ |
235 throws UnknownHostException { | 245 return new Socks5Message(in); |
236 if (resolveAddrLocally) | 246 } |
237 return formMessage(cmd, InetAddress.getByName(host), port); | |
238 else | |
239 return new Socks5Message(cmd, host, port); | |
240 } | |
241 @Override | |
242 protected ProxyMessage formMessage(InputStream in) | |
243 throws SocksException, | |
244 IOException { | |
245 return new Socks5Message(in); | |
246 } | |
247 | 247 |
248 } | 248 } |