1 28 29 package HTTPClient; 30 31 32 import java.io.*; 33 import java.net.*; 34 35 54 55 class SocksClient implements GlobalConstants 56 { 57 58 private String socks_host; 59 60 61 private int socks_port; 62 63 64 private int socks_version; 65 66 67 private final static byte CONNECT = 1, 68 BIND = 2, 69 UDP_ASS = 3; 70 71 72 private final static byte NO_AUTH = 0, 73 GSSAPI = 1, 74 USERPWD = 2, 75 NO_ACC = (byte) 0xFF; 76 77 78 private final static byte IP_V4 = 1, 79 DMNAME = 3, 80 IP_V6 = 4; 81 82 83 85 93 SocksClient(String host, int port) 94 { 95 this.socks_host = host; 96 this.socks_port = port; 97 this.socks_version = -1; } 99 100 110 SocksClient(String host, int port, int version) throws SocksException 111 { 112 this.socks_host = host; 113 this.socks_port = port; 114 115 if (version != 4 && version != 5) 116 throw new SocksException("SOCKS Version not supported: "+version); 117 this.socks_version = version; 118 } 119 120 121 123 132 Socket getSocket(String host, int port) throws IOException 133 { 134 Socket sock = null; 135 136 try 137 { 138 if (DebugSocks) 139 System.err.println("Socks: contacting server on " + 140 socks_host + ":" + socks_port); 141 142 143 145 sock = connect(socks_host, socks_port); 146 InputStream inp = sock.getInputStream(); 147 OutputStream out = sock.getOutputStream(); 148 149 150 152 switch (socks_version) 153 { 154 case 4: 155 v4ProtExchg(inp, out, host, port); 156 break; 157 case 5: 158 v5ProtExchg(inp, out, host, port); 159 break; 160 case -1: 161 try 163 { 164 v4ProtExchg(inp, out, host, port); 165 socks_version = 4; 166 } 167 catch (SocksException se) 168 { 169 if (DebugSocks) 170 System.err.println("Socks: V4 request failed: " + 171 se.getMessage()); 172 173 sock.close(); 174 sock = connect(socks_host, socks_port); 175 inp = sock.getInputStream(); 176 out = sock.getOutputStream(); 177 178 v5ProtExchg(inp, out, host, port); 179 socks_version = 5; 180 } 181 break; 182 default: 183 throw new Error ("SocksClient internal error: unknown " + 184 "version "+socks_version); 185 } 186 187 if (DebugSocks) 188 System.err.println("Socks: connection established."); 189 190 return sock; 191 } 192 catch (IOException ioe) 193 { 194 if (sock != null) 195 { 196 try { sock.close(); } 197 catch (IOException ee) {} 198 } 199 200 throw ioe; 201 } 202 } 203 204 205 212 private static final Socket connect(String host, int port) 213 throws IOException 214 { 215 InetAddress[] addr_list = InetAddress.getAllByName(host); 216 for (int idx=0; idx<addr_list.length; idx++) 217 { 218 try 219 { return new Socket(addr_list[idx], port); } 220 catch (SocketException se) 221 { 222 if (idx < addr_list.length-1) 223 continue; else 225 throw se; } 227 } 228 229 return null; } 231 232 233 private boolean v4A = false; private byte[] user = null; 235 236 239 private void v4ProtExchg(InputStream inp, OutputStream out, String host, 240 int port) 241 throws SocksException, IOException 242 { 243 ByteArrayOutputStream buffer = new ByteArrayOutputStream(100); 244 245 if (DebugSocks) 246 System.err.println("Socks: Beginning V4 Protocol Exchange for host " 247 + host + ":" + port); 248 249 251 byte[] addr = { 0, 0, 0, 42 }; 252 if (!v4A) 253 { 254 try 255 { addr = InetAddress.getByName(host).getAddress(); } 256 catch (UnknownHostException uhe) 258 { v4A = true; } 259 catch (SecurityException se) 260 { v4A = true; } 261 if (DebugSocks) 262 if (v4A) 263 System.err.println("Socks: Switching to version 4A"); 264 } 265 266 if (user == null) { 268 String user_str; 269 try 270 { user_str = System.getProperty("user.name", ""); } 271 catch (SecurityException se) 272 { user_str = ""; } 273 user = new byte[user_str.length()+1]; 274 user_str.getBytes(0, user_str.length(), user, 0); 275 user[user_str.length()] = 0; } 277 278 279 281 if (DebugSocks) 282 System.err.println("Socks: Sending connect request for user " + 283 new String (user, 0, 0, user.length-1)); 284 285 buffer.reset(); 286 buffer.write(4); buffer.write(CONNECT); buffer.write((port >> 8) & 0xff); buffer.write(port & 0xff); 290 buffer.write(addr, 0, addr.length); buffer.write(user, 0, user.length); if (v4A) 293 { 294 byte[] host_buf = new byte[host.length()]; 295 host.getBytes(0, host.length(), host_buf, 0); 296 buffer.write(host_buf, 0, host_buf.length); buffer.write(0); } 299 buffer.writeTo(out); 300 301 302 304 int version = inp.read(); 305 if (version == -1) 306 throw new SocksException("Connection refused by server"); 307 else if (version == 4) if (DebugSocks) 309 System.err.println("Socks: Warning: received version 4 " + 310 "instead of 0"); 311 else if (version != 0) 312 throw new SocksException("Received invalid version: " + version + 313 "; expected: 0"); 314 315 int sts = inp.read(); 316 317 if (DebugSocks) 318 System.err.println("Socks: Received response; version: " + version + 319 "; status: " + sts); 320 321 switch (sts) 322 { 323 case 90: break; 325 case 91: throw new SocksException("Connection request rejected"); 327 case 92: throw new SocksException("Connection request rejected: " + 329 "can't connect to identd"); 330 case 93: throw new SocksException("Connection request rejected: " + 332 "identd reports different user-id " + 333 "from "+ 334 new String (user, 0, 0, user.length-1)); 335 default: throw new SocksException("Connection request rejected: " + 337 "unknown error " + sts); 338 } 339 340 byte[] skip = new byte[2+4]; int rcvd = 0, 342 tot = 0; 343 while (tot < skip.length && 344 (rcvd = inp.read(skip, 0, skip.length-tot)) != -1) 345 tot += rcvd; 346 } 347 348 349 353 private void v5ProtExchg(InputStream inp, OutputStream out, String host, 354 int port) 355 throws SocksException, IOException 356 { 357 int version; 358 ByteArrayOutputStream buffer = new ByteArrayOutputStream(100); 359 360 if (DebugSocks) 361 System.err.println("Socks: Beginning V5 Protocol Exchange for host " 362 + host + ":" + port); 363 364 366 if (DebugSocks) 367 System.err.println("Socks: Sending authentication request; methods" 368 + " No-Authentication, Username/Password"); 369 370 buffer.reset(); 371 buffer.write(5); buffer.write(2); buffer.write(NO_AUTH); buffer.write(USERPWD); buffer.writeTo(out); 377 378 379 381 version = inp.read(); 382 if (version == -1) 383 throw new SocksException("Connection refused by server"); 384 else if (version != 5) 385 throw new SocksException("Received invalid version: " + version + 386 "; expected: 5"); 387 388 int method = inp.read(); 389 390 if (DebugSocks) 391 System.err.println("Socks: Received response; version: " + version + 392 "; method: " + method); 393 394 395 397 switch(method) 398 { 399 case NO_AUTH: 400 break; 401 case GSSAPI: 402 negotiate_gssapi(inp, out); 403 break; 404 case USERPWD: 405 negotiate_userpwd(inp, out); 406 break; 407 case NO_ACC: 408 throw new SocksException("Server unwilling to accept any " + 409 "standard authentication methods"); 410 default: 411 throw new SocksException("Cannot handle authentication method " 412 + method); 413 } 414 415 416 418 if (DebugSocks) 419 System.err.println("Socks: Sending connect request"); 420 421 buffer.reset(); 422 buffer.write(5); buffer.write(CONNECT); buffer.write(0); buffer.write(DMNAME); buffer.write(host.length() & 0xff); byte[] hname = new byte[host.length()]; 428 host.getBytes(0, host.length(), hname, 0); 429 buffer.write(hname, 0, hname.length); buffer.write((port >> 8) & 0xff); buffer.write(port & 0xff); 432 buffer.writeTo(out); 433 434 435 437 version = inp.read(); 438 if (version != 5) 439 throw new SocksException("Received invalid version: " + version + 440 "; expected: 5"); 441 442 int sts = inp.read(); 443 444 if (DebugSocks) 445 System.err.println("Socks: Received response; version: " + version + 446 "; status: " + sts); 447 448 switch (sts) 449 { 450 case 0: break; 452 case 1: 453 throw new SocksException("General SOCKS server failure"); 454 case 2: 455 throw new SocksException("Connection not allowed"); 456 case 3: 457 throw new SocksException("Network unreachable"); 458 case 4: 459 throw new SocksException("Host unreachable"); 460 case 5: 461 throw new SocksException("Connection refused"); 462 case 6: 463 throw new SocksException("TTL expired"); 464 case 7: 465 throw new SocksException("Command not supported"); 466 case 8: 467 throw new SocksException("Address type not supported"); 468 default: 469 throw new SocksException("Unknown reply received from server: " 470 + sts); 471 } 472 473 inp.read(); int atype = inp.read(), alen; switch(atype) 477 { 478 case IP_V6: 479 alen = 16; 480 break; 481 case IP_V4: 482 alen = 4; 483 break; 484 case DMNAME: 485 alen = inp.read(); 486 break; 487 default: 488 throw new SocksException("Invalid address type received from" + 489 " server: "+atype); 490 } 491 492 byte[] skip = new byte[alen+2]; int rcvd = 0, 494 tot = 0; 495 while (tot < skip.length && 496 (rcvd = inp.read(skip, 0, skip.length-tot)) != -1) 497 tot += rcvd; 498 } 499 500 501 508 private void negotiate_gssapi(InputStream inp, OutputStream out) 509 throws SocksException, IOException 510 { 511 throw new 512 SocksException("GSSAPI authentication protocol not implemented"); 513 } 514 515 516 525 private void negotiate_userpwd(InputStream inp, OutputStream out) 526 throws SocksException, IOException 527 { 528 byte[] buffer; 529 530 531 if (DebugSocks) 532 System.err.println("Socks: Entering authorization subnegotiation" + 533 "; method: Username/Password"); 534 535 537 AuthorizationInfo auth_info; 538 try 539 { 540 auth_info = 541 AuthorizationInfo.getAuthorization(socks_host, socks_port, 542 "SOCKS5", "USER/PASS", true); 543 } 544 catch (AuthSchemeNotImplException atnie) 545 { auth_info = null; } 546 547 if (auth_info == null) 548 throw new SocksException("No Authorization info for SOCKS found " + 549 "(server requested username/password)."); 550 551 NVPair[] unpw = auth_info.getParams(); 552 if (unpw == null || unpw.length == 0) 553 throw new SocksException("No Username/Password found in " + 554 "authorization info for SOCKS."); 555 556 String user_str = unpw[0].getName(); 557 String pass_str = unpw[0].getValue(); 558 559 560 562 if (DebugSocks) 563 System.err.println("Socks: Sending authorization request for user "+ 564 user_str); 565 566 buffer = new byte[1+1+user_str.length()+1+pass_str.length()]; 567 buffer[0] = 1; buffer[1] = (byte) user_str.length(); user_str.getBytes(0, buffer[1], buffer, 2); buffer[2+buffer[1]] = (byte) pass_str.length(); pass_str.getBytes(0, buffer[2+buffer[1]], buffer, 2+buffer[1]+1); out.write(buffer); 573 574 575 577 int version = inp.read(); 578 if (version != 1) 579 throw new SocksException("Wrong version received in username/" + 580 "password subnegotiation response: " + 581 version + "; expected: 1"); 582 583 int sts = inp.read(); 584 if (sts != 0) 585 throw new SocksException("Username/Password authentication " + 586 "failed; status: "+sts); 587 588 if (DebugSocks) 589 System.err.println("Socks: Received response; version: " + version + 590 "; status: " + sts); 591 } 592 593 594 598 public String toString() 599 { 600 return getClass().getName() + "[" + socks_host + ":" + socks_port + "]"; 601 } 602 } 603 604 | Popular Tags |