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