source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/net/SocksProxySocket.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 8.6 KB
Line 
1/******************************************************************************
2 *
3 * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4 * www.mindbright.se, [email protected]
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *****************************************************************************
17 * $Author: mats $
18 * $Date: 2000/03/30 13:36:58 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.net;
22import java.io.InputStream;
23import java.io.OutputStream;
24import java.io.IOException;
25import java.net.Socket;
26import java.net.InetAddress;
27import java.net.UnknownHostException;
28import java.net.SocketException;
29
30public class SocksProxySocket extends Socket {
31
32 private final static String[] replyErrorV5 = {
33 "Success",
34 "General SOCKS server failure",
35 "Connection not allowed by ruleset",
36 "Network unreachable",
37 "Host unreachable",
38 "Connection refused",
39 "TTL expired",
40 "Command not supported",
41 "Address type not supported"
42 };
43
44 private final static String[] replyErrorV4 = {
45 "Request rejected or failed",
46 "SOCKS server cannot connect to identd on the client",
47 "The client program and identd report different user-ids"
48 };
49
50 private String proxyHost;
51 private int proxyPort;
52 private String targetHost;
53 private int targetPort;
54
55 String serverDesc;
56
57 public String getServerDesc() {
58 return serverDesc;
59 }
60
61 private SocksProxySocket(String targetHost, int targetPort,
62 String proxyHost, int proxyPort)
63 throws IOException, UnknownHostException
64 {
65 super(proxyHost, proxyPort);
66
67 this.proxyHost = proxyHost;
68 this.proxyPort = proxyPort;
69 this.targetHost = targetHost;
70 this.targetPort = targetPort;
71 }
72
73 public static SocksProxySocket getSocks4Proxy(String targetHost,
74 int targetPort,
75 String proxyHost,
76 int proxyPort, String userId)
77 throws IOException, UnknownHostException
78 {
79 SocksProxySocket proxySocket =
80 new SocksProxySocket(targetHost, targetPort, proxyHost, proxyPort);
81
82 try {
83 InputStream proxyIn = proxySocket.getInputStream();
84 OutputStream proxyOut = proxySocket.getOutputStream();
85 InetAddress hostAddr = InetAddress.getByName(targetHost);
86
87 proxyOut.write(0x04); // V4
88 proxyOut.write(0x01); // CONNECT
89 proxyOut.write((targetPort >>> 8) & 0xff);
90 proxyOut.write(targetPort & 0xff);
91 proxyOut.write(hostAddr.getAddress());
92 proxyOut.write(userId.getBytes());
93 proxyOut.write(0x00); // NUL terminate userid string
94 proxyOut.flush();
95
96
97 int res = proxyIn.read();
98 if(res == -1) {
99 throw new IOException("SOCKS4 server " + proxyHost + ":" + proxyPort +
100 " disconnected");
101 }
102 if(res != 0x00)
103 throw new IOException("Invalid response from SOCKS4 server (" + res + ") " +
104 proxyHost + ":" + proxyPort);
105
106 int code = proxyIn.read();
107 if(code != 90) {
108 if(code > 90 && code < 93)
109 throw new IOException("SOCKS4 server unable to connect, reason: " +
110 replyErrorV4[code - 91]);
111 else
112 throw new IOException("SOCKS4 server unable to connect, reason: " +
113 code);
114 }
115
116 byte[] data = new byte[6];
117
118 if(proxyIn.read(data, 0, 6) != 6)
119 throw new IOException("SOCKS4 error reading destination address/port");
120
121 proxySocket.serverDesc = data[2] + "." + data[3] + "." + data[4] +
122 "." + data[5] + ":" + ((data[0] << 8) | data[1]);
123
124 } catch (SocketException e) {
125 throw new SocketException("Error communicating with SOCKS4 server " +
126 proxyHost + ":" + proxyPort + ", " +
127 e.getMessage());
128 }
129
130 return proxySocket;
131 }
132
133 public static SocksProxySocket getSocks5Proxy(String targetHost,
134 int targetPort,
135 String proxyHost,
136 int proxyPort,
137 boolean localLookup,
138 ProxyAuthenticator authenticator)
139 throws IOException, UnknownHostException
140 {
141 SocksProxySocket proxySocket =
142 new SocksProxySocket(targetHost, targetPort, proxyHost, proxyPort);
143
144 try {
145 InputStream proxyIn = proxySocket.getInputStream();
146 OutputStream proxyOut = proxySocket.getOutputStream();
147
148 // Simplest form, only no-auth and cleartext username/password
149 //
150 byte[] request = { (byte) 0x05, (byte) 0x02, (byte) 0x00, (byte) 0x02 };
151 byte[] reply = new byte[2];
152
153 proxyOut.write(request);
154 proxyOut.flush();
155
156 int res = proxyIn.read();
157 if(res == -1) {
158 throw new IOException("SOCKS5 server " + proxyHost + ":" + proxyPort +
159 " disconnected");
160 }
161 if(res != 0x05) {
162 throw new IOException("Invalid response from SOCKS5 server (" + res + ") " +
163 proxyHost + ":" + proxyPort);
164 }
165
166 int method = proxyIn.read();
167 switch(method) {
168 case 0x00:
169 break;
170 case 0x02:
171 doAuthentication(proxyIn, proxyOut, authenticator, proxyHost, proxyPort);
172 break;
173 default:
174 throw new IOException("SOCKS5 server does not support our authentication methods");
175 }
176
177 if(localLookup) {
178 // Request connect to targetHost (as 'ip-number') : targetPort
179 //
180 InetAddress hostAddr;
181 try {
182 hostAddr = InetAddress.getByName(targetHost);
183 } catch (UnknownHostException e) {
184 throw new IOException("Can't do local lookup on: " +
185 targetHost +
186 ", try socks5 without local lookup");
187 }
188 request = new byte[] { (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x01 };
189 proxyOut.write(request);
190 proxyOut.write(hostAddr.getAddress());
191 } else {
192 // Request connect to targetHost (as 'domain-name') : targetPort
193 //
194 request = new byte[] { (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x03 };
195 proxyOut.write(request);
196 proxyOut.write(targetHost.length());
197 proxyOut.write(targetHost.getBytes());
198 }
199 proxyOut.write((targetPort >>> 8) & 0xff);
200 proxyOut.write(targetPort & 0xff);
201 proxyOut.flush();
202
203 res = proxyIn.read();
204 if(res != 0x05)
205 throw new IOException("Invalid response from SOCKS5 server (" + res + ") " +
206 proxyHost + ":" + proxyPort);
207
208 int status = proxyIn.read();
209 if(status != 0x00) {
210 if(status > 0 && status < 9)
211 throw new IOException("SOCKS5 server unable to connect, reason: " +
212 replyErrorV5[status]);
213 else
214 throw new IOException("SOCKS5 server unable to connect, reason: " + status);
215 }
216
217 proxyIn.read(); // 0x00 RSV
218
219 int aType = proxyIn.read();
220 byte[] data = new byte[255];
221 switch(aType) {
222 case 0x01:
223 if(proxyIn.read(data, 0, 4) != 4)
224 throw new IOException("SOCKS5 error reading address");
225 proxySocket.serverDesc = data[0] + "." + data[1] + "." + data[2] +
226 "." + data[3];
227 break;
228 case 0x03:
229 int n = proxyIn.read();
230 if(proxyIn.read(data, 0, n) != n)
231 throw new IOException("SOCKS5 error reading address");
232 proxySocket.serverDesc = new String(data);
233 break;
234 default:
235 throw new IOException("SOCKS5 gave unsupported address type: " + aType);
236 }
237
238 if(proxyIn.read(data, 0, 2) != 2)
239 throw new IOException("SOCKS5 error reading port");
240 proxySocket.serverDesc += ":" + ((data[0] << 8) | data[1]);
241
242 } catch (SocketException e) {
243 throw new SocketException("Error communicating with SOCKS5 server " +
244 proxyHost + ":" + proxyPort + ", " +
245 e.getMessage());
246 }
247
248 return proxySocket;
249 }
250
251 static void doAuthentication(InputStream proxyIn, OutputStream proxyOut,
252 ProxyAuthenticator authenticator,
253 String proxyHost, int proxyPort) throws IOException {
254 String username = authenticator.getProxyUsername("SOCKS5", null);
255 String password = authenticator.getProxyPassword("SOCKS5", null);
256
257 proxyOut.write(0x01);
258 proxyOut.write(username.length());
259 proxyOut.write(username.getBytes());
260 proxyOut.write(password.length());
261 proxyOut.write(password.getBytes());
262
263 int res = proxyIn.read();
264 if(res != 0x05)
265 throw new IOException("Invalid response from SOCKS5 server (" + res + ") " +
266 proxyHost + ":" + proxyPort);
267
268 if(proxyIn.read() != 0x00)
269 throw new IOException("Invalid username/password for SOCKS5 server");
270 }
271
272 public String toString() {
273 return "SocksProxySocket[addr=" + getInetAddress() +
274 ",port=" + getPort() +
275 ",localport=" + getLocalPort() + "]";
276 }
277
278}
Note: See TracBrowser for help on using the repository browser.