From 8ffcc11f278994b5bd2cebe2ee50b78a9d14a985 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 29 Nov 2015 16:31:51 +0100 Subject: refactored socks5 connection code. make jingle transport use that new code --- src/main/java/eu/siacs/conversations/Config.java | 2 +- .../conversations/utils/SocksSocketFactory.java | 52 ++++++++++++++++++++++ .../siacs/conversations/xmpp/XmppConnection.java | 29 +++--------- .../xmpp/jingle/JingleSocks5Transport.java | 42 ++++++----------- 4 files changed, 72 insertions(+), 53 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index ddeba611..8c052845 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -42,7 +42,7 @@ public final class Config { public static final int REFRESH_UI_INTERVAL = 500; public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb - public static final boolean DISABLE_HTTP_UPLOAD = false; + public static final boolean DISABLE_HTTP_UPLOAD = true; public static final boolean DISABLE_STRING_PREP = false; // setting to true might increase startup performance public static final boolean EXTENDED_SM_LOGGING = true; // log stanza counts public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption diff --git a/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java b/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java new file mode 100644 index 00000000..6d9340ab --- /dev/null +++ b/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java @@ -0,0 +1,52 @@ +package eu.siacs.conversations.utils; + +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; + +import eu.siacs.conversations.Config; + +public class SocksSocketFactory { + + public static void createSocksConnection(Socket socket, String destination, int port) throws IOException { + InputStream proxyIs = socket.getInputStream(); + OutputStream proxyOs = socket.getOutputStream(); + proxyOs.write(new byte[]{0x05, 0x01, 0x00}); + byte[] response = new byte[2]; + proxyIs.read(response); + byte[] dest = destination.getBytes(); + ByteBuffer request = ByteBuffer.allocate(7 + dest.length); + request.put(new byte[]{0x05, 0x01, 0x00, 0x03}); + request.put((byte) dest.length); + request.put(dest); + request.putShort((short) port); + proxyOs.write(request.array()); + response = new byte[7 + dest.length]; + proxyIs.read(response); + if (response[1] != 0x00) { + throw new SocksConnectionException(); + } + } + + public static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException { + Socket socket = new Socket(); + socket.connect(address, Config.CONNECT_TIMEOUT * 1000); + createSocksConnection(socket, destination, port); + return socket; + } + + public static Socket createSocketOverTor(String destination, int port) throws IOException { + return createSocket(new InetSocketAddress(InetAddress.getLocalHost(), 9050), destination, port); + } + + static class SocksConnectionException extends IOException { + + } +} diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index f5f3860c..388f6572 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -67,6 +67,7 @@ import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.DNSHelper; +import eu.siacs.conversations.utils.SocksSocketFactory; import eu.siacs.conversations.utils.Xmlns; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Tag; @@ -235,32 +236,14 @@ public class XmppConnection implements Runnable { this.changeStatus(Account.State.CONNECTING); final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion(); if (useTor) { - InetSocketAddress proxyAddress = new InetSocketAddress(InetAddress.getLocalHost(), 9050); - byte[] destination; + String destination; if (account.getHostname() == null || account.getHostname().isEmpty()) { - destination = account.getServer().toString().getBytes(); + destination = account.getServer().toString(); } else { - destination = account.getHostname().getBytes(); - } - Log.d(Config.LOGTAG,"connecting via tor to "+new String(destination)); - socket = new Socket(); - socket.connect(proxyAddress, Config.CONNECT_TIMEOUT * 1000); - InputStream proxyIs = socket.getInputStream(); - OutputStream proxyOs = socket.getOutputStream(); - proxyOs.write(new byte[]{0x05, 0x01, 0x00}); - byte[] response = new byte[2]; - proxyIs.read(response); - ByteBuffer request = ByteBuffer.allocate(7 + destination.length); - request.put(new byte[]{0x05, 0x01, 0x00, 0x03}); - request.put((byte) destination.length); - request.put(destination); - request.putShort((short) account.getPort()); - proxyOs.write(request.array()); - response = new byte[7 + destination.length]; - proxyIs.read(response); - if (response[1] != 0x00) { - throw new UnknownHostException(); + destination = account.getHostname(); } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": connect to "+destination+" via TOR"); + socket = SocksSocketFactory.createSocketOverTor(destination,account.getPort()); } else if (DNSHelper.isIp(account.getServer().toString())) { socket = new Socket(); try { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java index 74306ce3..9240bd2c 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -21,6 +21,7 @@ import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.utils.SocksSocketFactory; public class JingleSocks5Transport extends JingleTransport { private JingleCandidate candidate; @@ -61,36 +62,19 @@ public class JingleSocks5Transport extends JingleTransport { @Override public void run() { try { - final boolean useTor = connection.getConnectionManager().getXmppConnectionService().useTorToConnect(); - final Proxy TOR_PROXY = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(InetAddress.getLocalHost(), 9050)); - socket = useTor ? new Socket(TOR_PROXY) : new Socket(); - SocketAddress address = new InetSocketAddress(candidate.getHost(),candidate.getPort()); - socket.connect(address,Config.SOCKET_TIMEOUT * 1000); - inputStream = socket.getInputStream(); - outputStream = socket.getOutputStream(); - byte[] login = { 0x05, 0x01, 0x00 }; - byte[] expectedReply = { 0x05, 0x00 }; - byte[] reply = new byte[2]; - outputStream.write(login); - inputStream.read(reply); - final String connect = Character.toString('\u0005') - + '\u0001' + '\u0000' + '\u0003' + '\u0028' - + destination + '\u0000' + '\u0000'; - if (Arrays.equals(reply, expectedReply)) { - outputStream.write(connect.getBytes()); - byte[] result = new byte[2]; - inputStream.read(result); - int status = result[1]; - if (status == 0) { - isEstablished = true; - callback.established(); - } else { - callback.failed(); - } + final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect(); + if (useTor) { + socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(),candidate.getPort()); } else { - socket.close(); - callback.failed(); + socket = new Socket(); + SocketAddress address = new InetSocketAddress(candidate.getHost(),candidate.getPort()); + socket.connect(address,Config.SOCKET_TIMEOUT * 1000); } + inputStream = socket.getInputStream(); + outputStream = socket.getOutputStream(); + SocksSocketFactory.createSocksConnection(socket,destination,0); + isEstablished = true; + callback.established(); } catch (UnknownHostException e) { callback.failed(); } catch (IOException e) { @@ -162,7 +146,7 @@ public class JingleSocks5Transport extends JingleTransport { wakeLock.acquire(); MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.reset(); - inputStream.skip(45); + //inputStream.skip(45); socket.setSoTimeout(30000); file.getParentFile().mkdirs(); file.createNewFile(); -- cgit v1.2.3