refactored socks5 connection code. make jingle transport use that new code

This commit is contained in:
Daniel Gultsch 2015-11-29 16:31:51 +01:00
parent ebccb67a72
commit 8ffcc11f27
4 changed files with 72 additions and 53 deletions

View File

@ -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

View File

@ -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 {
}
}

View File

@ -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 {

View File

@ -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);
final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect();
if (useTor) {
socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(),candidate.getPort());
} else {
socket = 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();
}
} else {
socket.close();
callback.failed();
}
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();