From 5fa4537a4689238f432526a776d7f4908b0d339f Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Tue, 15 Sep 2015 12:26:36 -0700 Subject: Change SOCKS library to simplesocks simplesocks only implements what we need and is 100% test covered! --- sshlib/build.gradle | 4 +- .../trilead/ssh2/channel/DynamicAcceptThread.java | 159 +++++---------------- 2 files changed, 39 insertions(+), 124 deletions(-) diff --git a/sshlib/build.gradle b/sshlib/build.gradle index ff1fe10..62de4fe 100644 --- a/sshlib/build.gradle +++ b/sshlib/build.gradle @@ -13,12 +13,12 @@ apply from: "${rootDir}/publish.gradle" repositories { maven { - url 'https://dl.bintray.com/kruton/maven' + url 'https://dl.bintray.com/connectbot/maven/' } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.jcraft:jzlib:1.1.3' - compile 'org.connectbot.jsocks:jsocks:1.0.0' + compile 'org.connectbot:simplesocks:1.0.1' } diff --git a/sshlib/src/main/java/com/trilead/ssh2/channel/DynamicAcceptThread.java b/sshlib/src/main/java/com/trilead/ssh2/channel/DynamicAcceptThread.java index ef3a3d0..5399e82 100644 --- a/sshlib/src/main/java/com/trilead/ssh2/channel/DynamicAcceptThread.java +++ b/sshlib/src/main/java/com/trilead/ssh2/channel/DynamicAcceptThread.java @@ -17,26 +17,15 @@ package com.trilead.ssh2.channel; +import org.connectbot.simplesocks.Socks5Server; + import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.io.OutputStream; -import java.io.PushbackInputStream; -import java.net.ConnectException; -import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.NoRouteToHostException; import java.net.ServerSocket; import java.net.Socket; -import net.sourceforge.jsocks.Proxy; -import net.sourceforge.jsocks.ProxyMessage; -import net.sourceforge.jsocks.Socks4Message; -import net.sourceforge.jsocks.Socks5Message; -import net.sourceforge.jsocks.SocksException; -import net.sourceforge.jsocks.server.ServerAuthenticator; -import net.sourceforge.jsocks.server.ServerAuthenticatorNone; - /** * DynamicAcceptThread. * @@ -50,14 +39,11 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread class DynamicAcceptRunnable implements Runnable { private static final int idleTimeout = 180000; //3 minutes - private ServerAuthenticator auth; private Socket sock; private InputStream in; private OutputStream out; - private ProxyMessage msg; - public DynamicAcceptRunnable(ServerAuthenticator auth, Socket sock) { - this.auth = auth; + public DynamicAcceptRunnable(Socket sock) { this.sock = sock; setName("DynamicAcceptRunnable"); @@ -67,116 +53,43 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread try { startSession(); } catch (IOException ioe) { - int error_code = Proxy.SOCKS_FAILURE; - - if (ioe instanceof SocksException) - error_code = ((SocksException) ioe).errCode; - else if (ioe instanceof NoRouteToHostException) - error_code = Proxy.SOCKS_HOST_UNREACHABLE; - else if (ioe instanceof ConnectException) - error_code = Proxy.SOCKS_CONNECTION_REFUSED; - else if (ioe instanceof InterruptedIOException) - error_code = Proxy.SOCKS_TTL_EXPIRE; - - if (error_code > Proxy.SOCKS_ADDR_NOT_SUPPORTED - || error_code < 0) { - error_code = Proxy.SOCKS_FAILURE; + try { + sock.close(); + } catch (IOException ignore) { } - - sendErrorMessage(error_code); - } finally { - if (auth != null) - auth.endSession(); - } - } - - private ProxyMessage readMsg(InputStream in) throws IOException { - PushbackInputStream push_in; - if (in instanceof PushbackInputStream) - push_in = (PushbackInputStream) in; - else - push_in = new PushbackInputStream(in); - - int version = push_in.read(); - push_in.unread(version); - - ProxyMessage msg; - - if (version == 5) { - msg = new Socks5Message(push_in, false); - } else if (version == 4) { - msg = new Socks4Message(push_in, false); - } else { - throw new SocksException(Proxy.SOCKS_FAILURE); - } - return msg; - } - - private void sendErrorMessage(int error_code) { - ProxyMessage err_msg; - if (msg instanceof Socks4Message) - err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); - else - err_msg = new Socks5Message(error_code); - try { - err_msg.write(out); - } catch (IOException ioe) { - } - } - - private void handleRequest(ProxyMessage msg) throws IOException { - if (!auth.checkRequest(msg)) - throw new SocksException(Proxy.SOCKS_FAILURE); - - switch (msg.command) { - case Proxy.SOCKS_CMD_CONNECT: - onConnect(msg); - break; - default: - throw new SocksException(Proxy.SOCKS_CMD_NOT_SUPPORTED); } } private void startSession() throws IOException { sock.setSoTimeout(idleTimeout); + in = sock.getInputStream(); + out = sock.getOutputStream(); + Socks5Server server = new Socks5Server(in, out); try { - auth = auth.startSession(sock); + if (!server.acceptAuthentication() || !server.readRequest()) { + System.out.println("Could not start SOCKS session"); + return; + } } catch (IOException ioe) { - System.out.println("Could not start SOCKS session"); - ioe.printStackTrace(); - auth = null; + server.sendReply(Socks5Server.ResponseCode.GENERAL_FAILURE); return; } - if (auth == null) { // Authentication failed - System.out.println("SOCKS auth failed"); - return; + if (server.getCommand() == Socks5Server.Command.CONNECT) { + onConnect(server); + } else { + server.sendReply(Socks5Server.ResponseCode.COMMAND_NOT_SUPPORTED); } - - in = auth.getInputStream(); - out = auth.getOutputStream(); - - msg = readMsg(in); - handleRequest(msg); } - private void onConnect(ProxyMessage msg) throws IOException { - ProxyMessage response = null; - Channel cn = null; - StreamForwarder r2l = null; - StreamForwarder l2r = null; + private void onConnect(Socks5Server server) throws IOException { + final Channel cn; - if (msg instanceof Socks5Message) { - response = new Socks5Message(Proxy.SOCKS_SUCCESS, (InetAddress)null, 0); - } else { - response = new Socks4Message(Socks4Message.REPLY_OK, (InetAddress)null, 0); + String destHost = server.getHostName(); + if (destHost == null) { + destHost = server.getAddress().getHostAddress(); } - response.write(out); - - String destHost = msg.host; - if (msg.ip != null) - destHost = msg.ip.getHostAddress(); try { /* @@ -184,14 +97,17 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread * optimistic terms: not open yet) */ - cn = cm.openDirectTCPIPChannel(destHost, msg.port, + cn = cm.openDirectTCPIPChannel(destHost, server.getPort(), "127.0.0.1", 0); } catch (IOException e) { /* - * Simply close the local socket and wait for the next incoming - * connection + * Try to send a notification back to the client and then close the socket. */ + try { + server.sendReply(Socks5Server.ResponseCode.GENERAL_FAILURE); + } catch (IOException ignore) { + } try { sock.close(); @@ -201,6 +117,10 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread return; } + server.sendReply(Socks5Server.ResponseCode.SUCCESS); + + final StreamForwarder r2l; + final StreamForwarder l2r; try { r2l = new StreamForwarder(cn, null, sock, cn.stdoutStream, out, "RemoteToLocal"); l2r = new StreamForwarder(cn, r2l, sock, in, cn.stdinStream, "LocalToRemote"); @@ -253,8 +173,7 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread } while (true) { - Socket sock = null; - + final Socket sock; try { sock = ss.accept(); } catch (IOException e) { @@ -262,23 +181,19 @@ public class DynamicAcceptThread extends Thread implements IChannelWorkerThread return; } - DynamicAcceptRunnable dar = new DynamicAcceptRunnable(new ServerAuthenticatorNone(), sock); + DynamicAcceptRunnable dar = new DynamicAcceptRunnable(sock); Thread t = new Thread(dar); t.setDaemon(true); t.start(); } } - /* - * (non-Javadoc) - * - * @see com.trilead.ssh2.channel.IChannelWorkerThread#stopWorking() - */ + @Override public void stopWorking() { try { /* This will lead to an IOException in the ss.accept() call */ ss.close(); - } catch (IOException e) { + } catch (IOException ignore) { } } } -- cgit v1.2.3