1 /************************************************************
2 * Copyright *
3 * Portions of this software are Copyright (c) 1993 - 2002, *
4 * Chad Z. Hower (Kudzu) and the Indy Pit Crew *
5 * - http://www.nevrona.com/Indy/ *
6 ************************************************************/
7 package org.indy.socks;
8
9 import org.indy.IndyComponent;
10
11 import org.indy.io.IOHandler;
12 import org.indy.io.IndyIOException;
13 import org.indy.io.ReadTimedOutException;
14
15 import org.indy.util.IndyUtilities;
16
17
18 /***
19 * Description of the Class
20 *
21 *@author owen
22 */
23 public class SocksInfo extends IndyComponent {
24 /***
25 * Description of the Field
26 */
27 protected Authentication authentication = Authentication.NO_AUTHENTICATION;
28
29 /***
30 * Description of the Field
31 */
32 protected String host = null;
33
34 /***
35 * Description of the Field
36 */
37 protected int port = 0;
38
39 /***
40 * Description of the Field
41 */
42 protected String username = null;
43
44 /***
45 * Description of the Field
46 */
47 protected String password = null;
48
49 /***
50 * Description of the Field
51 */
52 protected Version version = Version.NOSOCKS;
53
54 /***
55 * Description of the Field
56 */
57 protected IOHandler ioHandler = null;
58
59 /***
60 * Constructor for the IdSocksInfo object
61 *
62 *@param soInfo Description of the Parameter
63 */
64 public SocksInfo(SocksInfo soInfo) {
65 this.authentication = soInfo.authentication;
66 this.host = soInfo.host;
67 this.username = soInfo.username;
68 this.password = soInfo.password;
69 this.port = soInfo.port;
70 this.version = soInfo.version;
71 }
72
73 /***
74 * Constructor for the IdSocksInfo object
75 */
76 public SocksInfo() {
77 }
78
79 /***
80 * Sets the authentication attribute of the IdSocksInfo object
81 *
82 *@param newAuthentication The new authentication value
83 */
84 public void setAuthentication(SocksInfo.Authentication newAuthentication) {
85 authentication = newAuthentication;
86 }
87
88 /***
89 * Sets the host attribute of the IdSocksInfo object
90 *
91 *@param _host The new host value
92 */
93 public void setHost(String _host) {
94 host = _host;
95 }
96
97 /***
98 * Sets the port attribute of the IdSocksInfo object
99 *
100 *@param _port The new port value
101 */
102 public void setPort(int _port) {
103 port = _port;
104 }
105
106 /***
107 * Sets the username attribute of the IdSocksInfo object
108 *
109 *@param _username The new username value
110 */
111 public void setUsername(String _username) {
112 username = _username;
113 }
114
115 /***
116 * Sets the password attribute of the IdSocksInfo object
117 *
118 *@param _password The new password value
119 */
120 public void setPassword(String _password) {
121 password = _password;
122 }
123
124 /***
125 * Sets the socksVersion attribute of the IdSocksInfo object
126 *
127 *@param _version The new socksVersion value
128 */
129 public void setSocksVersion(SocksInfo.Version _version) {
130 version = _version;
131 }
132
133 /***
134 * Sets the ioHandler attribute of the IdSocksInfo object
135 *
136 *@param _ioHandler The new ioHandler value
137 */
138 public void setIoHandler(IOHandler _ioHandler) {
139 ioHandler = _ioHandler;
140 }
141
142 /***
143 * Gets the authentication attribute of the IdSocksInfo object
144 *
145 *@return The authentication value
146 */
147 public SocksInfo.Authentication getAuthentication() {
148 return authentication;
149 }
150
151 /***
152 * Gets the host attribute of the IdSocksInfo object
153 *
154 *@return The host value
155 */
156 public String getHost() {
157 return host;
158 }
159
160 /***
161 * Gets the port attribute of the IdSocksInfo object
162 *
163 *@return The port value
164 */
165 public int getPort() {
166 return port;
167 }
168
169 /***
170 * Gets the username attribute of the IdSocksInfo object
171 *
172 *@return The username value
173 */
174 public String getUsername() {
175 return username;
176 }
177
178 /***
179 * Gets the password attribute of the IdSocksInfo object
180 *
181 *@return The password value
182 */
183 public String getPassword() {
184 return password;
185 }
186
187 /***
188 * Gets the socksVersion attribute of the IdSocksInfo object
189 *
190 *@return The socksVersion value
191 */
192 public Version getSocksVersion() {
193 return version;
194 }
195
196 /***
197 * Description of the Method
198 *
199 *@param host Description of the Parameter
200 *@param port Description of the Parameter
201 *@throws IdSocksError Description of the Exception
202 */
203 public void makeSocksConnection(String host, int port)
204 throws SocksException, ReadTimedOutException {
205 if ((version == Version.SOCKS4) || (version == Version.SOCKS4A)) {
206 makeSocks4Connection(host, port);
207 }
208 else if (version == Version.SOCKS5) {
209 makeSocks5Connection(host, port);
210 }
211 }
212
213 /***
214 * Description of the Method
215 *
216 *@param host Description of the Parameter
217 *@param port Description of the Parameter
218 *@throws IdSocksError Description of the Exception
219 */
220 public void makeSocks4Connection(String host, int port)
221 throws SocksException, ReadTimedOutException {
222 byte[] request = new byte[263];
223
224 request[0] = 4;
225 request[1] = 1;
226 request[2] = (byte) (port & 0xFF00);
227 request[3] = (byte) (port & 0xFF);
228
229 int pos = 4;
230
231 if (version == Version.SOCKS4A) {
232 request[4] = 0;
233 request[5] = 0;
234 request[6] = 0;
235 request[7] = 1;
236 }
237 else {
238 /*** @todo NO java.net call here!! */
239
240 //probably should delegate java.net call elsewhere
241 try {
242 java.net.InetAddress ia = java.net.InetAddress.getByName(host);
243 byte[] addr = ia.getAddress();
244
245 request[4] = addr[0];
246 request[5] = addr[1];
247 request[6] = addr[2];
248 request[7] = addr[3];
249 }
250 catch (java.net.UnknownHostException uhe) {
251 //argghh
252 throw new SocksUnknownHostException("Unknown host " + host);
253 }
254 }
255
256 pos = 8;
257
258 System.arraycopy(username.getBytes(), 0, request, pos, username.length());
259 pos += username.length();
260 request[pos] = '\000';
261 pos++;
262
263 if (version == Version.SOCKS4A) {
264 System.arraycopy(host.getBytes(), 0, request, pos, host.length());
265 pos += host.length();
266 request[pos++] = '\000';
267 }
268
269 byte[] response = new byte[8];
270
271 try {
272 ioHandler.write(request, 0, 8);
273 ioHandler.read(response, 0, 8);
274 }
275 catch (IndyIOException ioe) {
276 throw new SocksServerRespondException(IndyUtilities.getResourceString(
277 "RSSocksServerRespondError"));
278 }
279
280 switch (response[1]) {
281 case 90:
282 break;
283
284 //success, do nothing
285 case 91:
286 throw new SocksRequestFailedException(IndyUtilities.getResourceString(
287 "RSSocksRequestFailed"));
288
289 case 92:
290 throw new SocksRequestServerFailedException(IndyUtilities.getResourceString(
291 "RSSocksRequestServerFailed"));
292
293 case 93:
294 throw new SocksRequestIdentFailedException(IndyUtilities.getResourceString(
295 "RSSocksRequestIdentFailed"));
296
297 default:
298 throw new SocksUnknownException(IndyUtilities.getResourceString(
299 "RSSocksUnknownError"));
300 }
301 }
302
303 /***
304 * Description of the Method
305 *
306 *@param host Description of the Parameter
307 *@param port Description of the Parameter
308 *@throws IdSocksError Description of the Exception
309 */
310 public void makeSocks5Connection(String host, int port)
311 throws SocksException, ReadTimedOutException {
312 byte[] tmpBuf = new byte[255];
313
314 if (authentication == Authentication.NO_AUTHENTICATION) {
315 tmpBuf[2] = 0x0;
316 }
317 else {
318 tmpBuf[2] = 0x2;
319 }
320
321 byte requestedAuthMethod = tmpBuf[2];
322
323 tmpBuf[0] = 0x5;
324
325
326 // socks version
327 tmpBuf[1] = 0x1;
328
329 //number of possible authentication methods
330 int len = 2 + tmpBuf[1];
331
332 try {
333 ioHandler.write(tmpBuf, 0, len);
334 ioHandler.read(tmpBuf, 0, 2);
335 }
336 catch (IndyIOException ioe) {
337 throw new SocksServerRespondException(IndyUtilities.getResourceString(
338 "RSSocksServerRespondError"));
339 }
340
341 byte serverAuthMethod = tmpBuf[1];
342
343 if ((serverAuthMethod != requestedAuthMethod) ||
344 (serverAuthMethod == 0xFF)) {
345 throw new SocksAuthMethodException(IndyUtilities.getResourceString(
346 "RSSocksAuthMethodError"));
347 }
348
349 if (authentication == Authentication.USERNAME_PASSWORD) {
350 if ((username == null) || (password == null)) {
351 //throw exception ??
352 }
353
354 tmpBuf[0] = 0x1;
355
356 //length of subnegotiation;
357 int ulen = (username == null) ? 0 : username.length();
358
359 tmpBuf[1] = (byte) ulen;
360
361 int pos = 2;
362
363 if ((ulen > 0) && (username != null)) {
364 System.arraycopy(username.getBytes(), 0, tmpBuf, pos, ulen);
365 }
366
367 pos += ulen;
368
369 int passlen = (password == null) ? 0 : password.length();
370
371 tmpBuf[pos] = (byte) passlen;
372 pos++;
373
374 if ((passlen > 0) && (password != null)) {
375 System.arraycopy(password.getBytes(), 0, tmpBuf, pos, passlen);
376 }
377
378 pos += passlen;
379
380 try {
381 ioHandler.write(tmpBuf, 0, pos);
382
383
384 //send the username and password
385 ioHandler.read(tmpBuf, 0, 2);
386 }
387 catch (IndyIOException ioe) {
388 throw new SocksServerRespondException(IndyUtilities.getResourceString(
389 "RSSocksServerRespondError"));
390 }
391
392 if (tmpBuf[1] != 0x0) {
393 throw new SocksAuthException(IndyUtilities.getResourceString(
394 "RSSocksAuthError"));
395 }
396 }
397
398
399 //Connection process
400 tmpBuf[0] = 0x5;
401
402
403 //socks version
404 tmpBuf[1] = 0x1;
405
406
407 //connect method
408 tmpBuf[2] = 0x0;
409
410
411 //reserved
412 tmpBuf[3] = 0x3;
413
414
415 //Domain name - must find out out about all this
416 //address type: IP v4 Address 0x1
417 // Domain name 0x3
418 // IP v6 Address 0x4
419 tmpBuf[4] = (byte) host.length();
420
421 int pos = 5;
422
423 if (host.length() > 0) {
424 System.arraycopy(host.getBytes(), 0, tmpBuf, pos, host.length());
425 }
426
427 pos += host.length();
428
429
430 //port
431 tmpBuf[pos] = (byte) (port & 0xFF00);
432 tmpBuf[pos++] = (byte) (port & 0xFF);
433 pos++;
434
435 try {
436 //send the connection packet
437 ioHandler.write(tmpBuf, 0, pos);
438
439
440 // Socks server replies on connect, this is the first part
441 ioHandler.read(tmpBuf, 0, 5);
442 }
443 catch (IndyIOException ioe) {
444 throw new SocksServerRespondException(IndyUtilities.getResourceString(
445 "RSSocksServerRespondError"));
446 }
447
448 switch (tmpBuf[1]) {
449 case 0:
450 break;
451
452 //success - do nothing
453 case 1:
454 throw new SocksServerGeneralException(IndyUtilities.getResourceString(
455 "RSSocksServerGeneralError"));
456
457 case 2:
458 throw new SocksServerPermissionException(IndyUtilities.getResourceString(
459 "RSSocksServerPermissionError"));
460
461 case 3:
462 throw new SocksServerNetUnreachableException(IndyUtilities.getResourceString(
463 "RSSocksServerNetUnreachableError"));
464
465 case 4:
466 throw new SocksServerHostUnreachableException(IndyUtilities.getResourceString(
467 "RSSocksServerHostUnreachableError"));
468
469 case 5:
470 throw new SocksServerConnectionRefusedException(IndyUtilities.getResourceString(
471 "RSSocksServerConnectionRefusedError"));
472
473 case 6:
474 throw new SocksServerTTLExpiredException(IndyUtilities.getResourceString(
475 "RSSocksServerTTLExpiredError"));
476
477 case 7:
478 throw new SocksServerCommandException(IndyUtilities.getResourceString(
479 "RSSocksServerCommandError"));
480
481 case 8:
482 throw new SocksServerAddressException(IndyUtilities.getResourceString(
483 "RSSocksServerAddressError"));
484
485 default:
486 throw new SocksUnknownException(IndyUtilities.getResourceString(
487 "RSSocksUnknownError"));
488 }
489
490 //type of destination address is domain name
491 switch (tmpBuf[3]) {
492 //IPv4
493 case 1:
494 len = 4 + 2;
495
496 break;
497
498 // 4 is for address and 2 is for port length
499 //FQDN
500 case 3:
501 len = tmpBuf[4] + 2;
502
503 break;
504
505 // 2 is for port length
506 //IPv6
507 case 4:
508 len = 16 + 2;
509
510 // 16 is for address and 2 is for port length
511 }
512
513 try {
514 // Socks server replies on connect, this is the second part
515 ioHandler.read(tmpBuf, 0, len - 1);
516
517 //
518 }
519 catch (IndyIOException ioe) {
520 throw new SocksServerRespondException(IndyUtilities.getResourceString(
521 "RSSocksServerRespondError"));
522 }
523 }
524
525 /***
526 * Description of the Class
527 *
528 *@author owen
529 */
530 public final static class Version {
531 /***
532 * Description of the Field
533 */
534 public final static Version NOSOCKS = new Version("No SOCKS");
535
536 /***
537 * Description of the Field
538 */
539 public final static Version SOCKS4 = new Version("SOCKS 4");
540
541 /***
542 * Description of the Field
543 */
544 public final static Version SOCKS4A = new Version("SOCKS 4A");
545
546 /***
547 * Description of the Field
548 */
549 public final static Version SOCKS5 = new Version("SOCKS 5");
550 private final String _desc;
551
552 private Version(String desc) {
553 _desc = desc;
554 }
555
556 /***
557 * Description of the Method
558 *
559 *@return Description of the Return Value
560 */
561 public String toString() {
562 return "SOCKS Version: " + _desc;
563 }
564 }
565
566 /***
567 * Description of the Class
568 *
569 *@author owen
570 */
571 public final static class Authentication {
572 /***
573 * Description of the Field
574 */
575 public final static Authentication NO_AUTHENTICATION =
576 new Authentication("None");
577
578 /***
579 * Description of the Field
580 */
581 public final static Authentication USERNAME_PASSWORD =
582 new Authentication("Username-Password");
583 private String _desc;
584
585 private Authentication(String desc) {
586 _desc = desc;
587 }
588
589 /***
590 * Description of the Method
591 *
592 *@return Description of the Return Value
593 */
594 public String toString() {
595 return "SOCKS Authentication: " + _desc;
596 }
597 }
598 }
This page was automatically generated by Maven