1 /* 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package test.java.net.Socks; 24 25 import java.net.*; 26 import java.io.*; 27 import java.util.HashMap; 28 29 public class SocksServer extends Thread { 30 // Some useful SOCKS constant 31 32 static final int PROTO_VERS4 = 4; 33 static final int PROTO_VERS = 5; 34 static final int DEFAULT_PORT = 1080; 35 36 static final int NO_AUTH = 0; 37 static final int GSSAPI = 1; 38 static final int USER_PASSW = 2; 39 static final int NO_METHODS = -1; 40 41 static final int CONNECT = 1; 42 static final int BIND = 2; 43 static final int UDP_ASSOC = 3; 44 45 static final int IPV4 = 1; 46 static final int DOMAIN_NAME = 3; 47 static final int IPV6 = 4; 48 49 static final int REQUEST_OK = 0; 50 static final int GENERAL_FAILURE = 1; 51 static final int NOT_ALLOWED = 2; 52 static final int NET_UNREACHABLE = 3; 53 static final int HOST_UNREACHABLE = 4; 54 static final int CONN_REFUSED = 5; 55 static final int TTL_EXPIRED = 6; 56 static final int CMD_NOT_SUPPORTED = 7; 57 static final int ADDR_TYPE_NOT_SUP = 8; 58 59 private int port; 60 private ServerSocket server; 61 private boolean useV4 = false; 62 private HashMap<String,String> users = new HashMap<>(); 63 private volatile boolean done = false; 64 // Inner class to handle protocol with client 65 // This is the bulk of the work (protocol handler) 66 class ClientHandler extends Thread { 67 private InputStream in; 68 private OutputStream out; 69 private Socket client; 70 private Socket dest; 71 72 // Simple tunneling class, moving bits from one stream to another 73 74 class Tunnel extends Thread { 75 private InputStream tin; 76 private OutputStream tout; 77 Tunnel(InputStream in, OutputStream out)78 Tunnel(InputStream in, OutputStream out) { 79 tin = in; 80 tout = out; 81 } 82 run()83 public void run() { 84 int b; 85 while (true) { 86 try { 87 b = tin.read(); 88 if (b == -1) { 89 tin.close(); 90 tout.close(); 91 return; 92 } 93 tout.write(b); 94 tout.flush(); 95 } catch (IOException e) { 96 // actually exit from the thread 97 return; 98 } 99 } 100 } 101 } 102 ClientHandler(Socket s)103 ClientHandler(Socket s) throws IOException { 104 client = s; 105 in = new BufferedInputStream(client.getInputStream()); 106 out = new BufferedOutputStream(client.getOutputStream()); 107 } 108 readBuf(InputStream is, byte[] buf)109 private void readBuf(InputStream is, byte[] buf) throws IOException { 110 int l = buf.length; 111 int count = 0; 112 int i; 113 do { 114 i = is.read(buf, count, l - count); 115 if (i == -1) 116 throw new IOException("unexpected EOF"); 117 count += i; 118 } while (count < l); 119 } 120 121 userPassAuth()122 private boolean userPassAuth() throws IOException { 123 int ver = in.read(); 124 int ulen = in.read(); 125 if (ulen <= 0) 126 throw new SocketException("SOCKS protocol error"); 127 byte[] buf = new byte[ulen]; 128 readBuf(in, buf); 129 String uname = new String(buf); 130 String password = null; 131 ulen = in.read(); 132 if (ulen < 0) 133 throw new SocketException("SOCKS protocol error"); 134 if (ulen > 0) { 135 buf = new byte[ulen]; 136 readBuf(in, buf); 137 password = new String(buf); 138 } 139 // Check username/password validity here 140 System.err.println("User: '" + uname); 141 System.err.println("PSWD: '" + password); 142 if (users.containsKey(uname)) { 143 String p1 = users.get(uname); 144 System.err.println("p1 = " + p1); 145 if (p1.equals(password)) { 146 out.write(PROTO_VERS); 147 out.write(REQUEST_OK); 148 out.flush(); 149 return true; 150 } 151 } 152 out.write(PROTO_VERS); 153 out.write(NOT_ALLOWED); 154 out.flush(); 155 return false; 156 } 157 purge()158 private void purge() throws IOException { 159 boolean done = false; 160 int i = 0; 161 client.setSoTimeout(1000); 162 while(!done && i != -1) { 163 try { 164 i = in.read(); 165 } catch(IOException e) { 166 done = true; 167 } 168 } 169 } 170 171 172 // Handle the SOCKS version 4 protocl 173 getRequestV4()174 private void getRequestV4() throws IOException { 175 int ver = in.read(); 176 int cmd = in.read(); 177 if (ver == -1 || cmd == -1) { 178 // EOF 179 in.close(); 180 out.close(); 181 return; 182 } 183 184 if (ver != 0 && ver != 4) { 185 out.write(PROTO_VERS4); 186 out.write(91); // Bad Request 187 out.write(0); 188 out.write(0); 189 out.write(0); 190 out.write(0); 191 out.write(0); 192 out.write(0); 193 out.write(0); 194 out.flush(); 195 purge(); 196 out.close(); 197 in.close(); 198 return; 199 } 200 201 if (cmd == CONNECT) { 202 int port = ((in.read() & 0xff) << 8); 203 port += (in.read() & 0xff); 204 byte[] buf = new byte[4]; 205 readBuf(in, buf); 206 InetAddress addr = InetAddress.getByAddress(buf); 207 // We don't use the username... 208 int c; 209 do { 210 c = (in.read() & 0xff); 211 } while (c!=0); 212 boolean ok = true; 213 try { 214 dest = new Socket(addr, port); 215 } catch (IOException e) { 216 ok = false; 217 } 218 if (!ok) { 219 out.write(PROTO_VERS4); 220 out.write(91); 221 out.write(0); 222 out.write(0); 223 out.write(buf); 224 out.flush(); 225 purge(); 226 out.close(); 227 in.close(); 228 return; 229 } 230 out.write(PROTO_VERS4); 231 out.write(90); // Success 232 out.write((port >> 8) & 0xff); 233 out.write(port & 0xff); 234 out.write(buf); 235 out.flush(); 236 InputStream in2 = new BufferedInputStream(dest.getInputStream()); 237 OutputStream out2 = new BufferedOutputStream(dest.getOutputStream()); 238 239 Tunnel tunnel = new Tunnel(in2, out); 240 tunnel.start(); 241 242 int b = 0; 243 do { 244 try { 245 b = in.read(); 246 if (b == -1) { 247 in.close(); 248 out2.close(); 249 return; 250 } 251 out2.write(b); 252 out2.flush(); 253 } catch (IOException ex) { 254 } 255 } while (!client.isClosed()); 256 } 257 } 258 259 260 // Negociate the authentication scheme with the client negociate()261 private void negociate() throws IOException { 262 int ver = in.read(); 263 int n = in.read(); 264 byte[] buf = null; 265 if (n > 0) { 266 buf = new byte[n]; 267 readBuf(in, buf); 268 } 269 int scheme = NO_AUTH; 270 for (int i = 0; i < n; i++) 271 if (buf[i] == USER_PASSW) 272 scheme = USER_PASSW; 273 out.write(PROTO_VERS); 274 out.write(scheme); 275 out.flush(); 276 if (scheme == USER_PASSW) 277 userPassAuth(); 278 } 279 280 // Send error message then close the streams sendError(int code)281 private void sendError(int code) { 282 try { 283 out.write(PROTO_VERS); 284 out.write(code); 285 out.write(0); 286 out.write(IPV4); 287 for (int i=0; i<6; i++) 288 out.write(0); 289 out.flush(); 290 out.close(); 291 } catch (IOException ex) { 292 } 293 } 294 295 // Actually connect the proxy to the destination then initiate tunneling 296 doConnect(InetSocketAddress addr)297 private void doConnect(InetSocketAddress addr) throws IOException { 298 dest = new Socket(); 299 try { 300 dest.connect(addr, 10000); 301 } catch (SocketTimeoutException ex) { 302 sendError(HOST_UNREACHABLE); 303 return; 304 } catch (ConnectException cex) { 305 sendError(CONN_REFUSED); 306 return; 307 } 308 // Success 309 InetAddress iadd = addr.getAddress(); 310 if (iadd instanceof Inet4Address) { 311 out.write(PROTO_VERS); 312 out.write(REQUEST_OK); 313 out.write(0); 314 out.write(IPV4); 315 out.write(iadd.getAddress()); 316 } else if (iadd instanceof Inet6Address) { 317 out.write(PROTO_VERS); 318 out.write(REQUEST_OK); 319 out.write(0); 320 out.write(IPV6); 321 out.write(iadd.getAddress()); 322 } else { 323 sendError(GENERAL_FAILURE); 324 return; 325 } 326 out.write((addr.getPort() >> 8) & 0xff); 327 out.write((addr.getPort() >> 0) & 0xff); 328 out.flush(); 329 330 InputStream in2 = new BufferedInputStream(dest.getInputStream()); 331 OutputStream out2 = new BufferedOutputStream(dest.getOutputStream()); 332 333 Tunnel tunnel = new Tunnel(in2, out); 334 tunnel.start(); 335 336 int b = 0; 337 do { 338 // Note that the socket might be closed from another thread (the tunnel) 339 try { 340 b = in.read(); 341 if (b == -1) { 342 in.close(); 343 out2.close(); 344 return; 345 } 346 out2.write(b); 347 out2.flush(); 348 } catch(IOException ioe) { 349 } 350 } while (!client.isClosed()); 351 } 352 doBind(InetSocketAddress addr)353 private void doBind(InetSocketAddress addr) throws IOException { 354 ServerSocket svr = new ServerSocket(); 355 svr.bind(null); 356 InetSocketAddress bad = (InetSocketAddress) svr.getLocalSocketAddress(); 357 out.write(PROTO_VERS); 358 out.write(REQUEST_OK); 359 out.write(0); 360 out.write(IPV4); 361 out.write(bad.getAddress().getAddress()); 362 out.write((bad.getPort() >> 8) & 0xff); 363 out.write((bad.getPort() & 0xff)); 364 out.flush(); 365 dest = svr.accept(); 366 bad = (InetSocketAddress) dest.getRemoteSocketAddress(); 367 out.write(PROTO_VERS); 368 out.write(REQUEST_OK); 369 out.write(0); 370 out.write(IPV4); 371 out.write(bad.getAddress().getAddress()); 372 out.write((bad.getPort() >> 8) & 0xff); 373 out.write((bad.getPort() & 0xff)); 374 out.flush(); 375 InputStream in2 = dest.getInputStream(); 376 OutputStream out2 = dest.getOutputStream(); 377 378 Tunnel tunnel = new Tunnel(in2, out); 379 tunnel.start(); 380 381 int b = 0; 382 do { 383 // Note that the socket might be close from another thread (the tunnel) 384 try { 385 b = in.read(); 386 if (b == -1) { 387 in.close(); 388 out2.close(); 389 return; 390 } 391 out2.write(b); 392 out2.flush(); 393 } catch(IOException ioe) { 394 } 395 } while (!client.isClosed()); 396 397 } 398 399 // Handle the SOCKS v5 requests 400 getRequest()401 private void getRequest() throws IOException { 402 int ver = in.read(); 403 int cmd = in.read(); 404 if (ver == -1 || cmd == -1) { 405 in.close(); 406 out.close(); 407 return; 408 } 409 int rsv = in.read(); 410 int atyp = in.read(); 411 String addr = null; 412 int port = 0; 413 414 switch(atyp) { 415 case IPV4: 416 { 417 byte[] buf = new byte[4]; 418 readBuf(in, buf); 419 addr = InetAddress.getByAddress(buf).getHostAddress(); 420 } 421 break; 422 case DOMAIN_NAME: 423 { 424 int i = in.read(); 425 byte[] buf = new byte[i]; 426 readBuf(in, buf); 427 addr = new String(buf); 428 } 429 break; 430 case IPV6: 431 { 432 byte[] buf = new byte[16]; 433 readBuf(in, buf); 434 addr = InetAddress.getByAddress(buf).getHostAddress(); 435 } 436 break; 437 } 438 439 port = ((in.read()&0xff) << 8); 440 port += (in.read()&0xff); 441 442 InetSocketAddress socAddr = new InetSocketAddress(addr, port); 443 switch(cmd) { 444 case CONNECT: 445 doConnect(socAddr); 446 break; 447 case BIND: 448 doBind(socAddr); 449 break; 450 case UDP_ASSOC: 451 // doUDP(socAddr); 452 break; 453 } 454 } 455 run()456 public void run() { 457 String line = null; 458 try { 459 if (useV4) { 460 getRequestV4(); 461 } else { 462 negociate(); 463 getRequest(); 464 } 465 } catch (IOException ex) { 466 try { 467 sendError(GENERAL_FAILURE); 468 } catch (Exception e) { 469 } 470 } finally { 471 try { 472 client.close(); 473 } catch (IOException e2) { 474 } 475 } 476 } 477 478 } 479 SocksServer(int port, boolean v4)480 public SocksServer(int port, boolean v4) throws IOException { 481 this(port); 482 this.useV4 = v4; 483 } 484 SocksServer(int port)485 public SocksServer(int port) throws IOException { 486 this.port = port; 487 server = new ServerSocket(); 488 if (port == 0) { 489 server.bind(null); 490 this.port = server.getLocalPort(); 491 } else { 492 server.bind(new InetSocketAddress(port)); 493 } 494 } 495 SocksServer()496 public SocksServer() throws IOException { 497 this (DEFAULT_PORT); 498 } 499 addUser(String user, String passwd)500 public void addUser(String user, String passwd) { 501 users.put(user, passwd); 502 } 503 getPort()504 public int getPort() { 505 return port; 506 } 507 terminate()508 public void terminate() { 509 done = true; 510 try { server.close(); } catch (IOException unused) {} 511 } 512 run()513 public void run() { 514 ClientHandler cl = null; 515 while (!done) { 516 try { 517 Socket s = server.accept(); 518 cl = new ClientHandler(s); 519 cl.start(); 520 } catch (IOException ex) { 521 if (cl != null) 522 cl.interrupt(); 523 } 524 } 525 } 526 } 527