aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java5
-rw-r--r--src/main/java/de/pixart/messenger/utils/SocksSocketFactory.java24
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java108
3 files changed, 71 insertions, 66 deletions
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
index 2378c429e..9d2d90838 100644
--- a/src/main/java/de/pixart/messenger/utils/Resolver.java
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -75,11 +75,14 @@ public class Resolver {
Result result = new Result();
result.hostname = DNSName.from(hostname);
result.port = port;
- result.directTls = port == 443 || port == 5223;
+ result.directTls = useDirectTls(port);
result.authenticated = true;
return Collections.singletonList(result);
}
+ public static boolean useDirectTls(final int port) {
+ return port == 443 || port == 5223;
+ }
public static List<Result> resolve(String domain) {
final List<Result> ipResults = fromIpAddress(domain);
diff --git a/src/main/java/de/pixart/messenger/utils/SocksSocketFactory.java b/src/main/java/de/pixart/messenger/utils/SocksSocketFactory.java
index 0bc27749a..365f77c6c 100644
--- a/src/main/java/de/pixart/messenger/utils/SocksSocketFactory.java
+++ b/src/main/java/de/pixart/messenger/utils/SocksSocketFactory.java
@@ -19,7 +19,7 @@ public class SocksSocketFactory {
byte[] response = new byte[2];
proxyIs.read(response);
if (response[0] != 0x05 || response[1] != 0x00) {
- throw new SocksConnectionException();
+ throw new SocksConnectionException("Socks 5 handshake failed");
}
byte[] dest = destination.getBytes();
ByteBuffer request = ByteBuffer.allocate(7 + dest.length);
@@ -31,12 +31,18 @@ public class SocksSocketFactory {
response = new byte[7 + dest.length];
proxyIs.read(response);
if (response[1] != 0x00) {
- throw new SocksConnectionException();
+ if (response[1] == 0x04) {
+ throw new HostNotFoundException("Host unreachable");
+ }
+ if (response[1] == 0x05) {
+ throw new HostNotFoundException("Connection refused");
+ }
+ throw new SocksConnectionException("Unable to connect to destination " + (int) (response[1]));
}
}
public static boolean contains(byte needle, byte[] haystack) {
- for(byte hay : haystack) {
+ for (byte hay : haystack) {
if (hay == needle) {
return true;
}
@@ -59,11 +65,19 @@ public class SocksSocketFactory {
return createSocket(new InetSocketAddress(InetAddress.getLocalHost(), 9050), destination, port);
}
- static class SocksConnectionException extends IOException {
-
+ private static class SocksConnectionException extends IOException {
+ SocksConnectionException(String message) {
+ super(message);
+ }
}
public static class SocksProxyNotFoundException extends IOException {
}
+
+ public static class HostNotFoundException extends SocksConnectionException {
+ HostNotFoundException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
index 01c19322b..54f72754c 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -293,8 +293,17 @@ public class XmppConnection implements Runnable {
destination = account.getHostname();
this.verifiedHostname = destination;
}
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor");
- localSocket = SocksSocketFactory.createSocketOverTor(destination, account.getPort());
+ final int port = account.getPort();
+ final boolean directTls = Resolver.useDirectTls(port);
+
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor. directTls=" + directTls);
+ localSocket = SocksSocketFactory.createSocketOverTor(destination, port);
+
+ if (directTls) {
+ localSocket = upgradeSocketToTls(localSocket);
+ features.encryptionEnabled = true;
+ }
+
try {
startXmpp(localSocket);
} catch (InterruptedException e) {
@@ -354,29 +363,13 @@ public class XmppConnection implements Runnable {
+ result.getHostname().toString() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
}
- if (!features.encryptionEnabled) {
- localSocket = new Socket();
- localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
- } else {
- final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
- localSocket = tlsFactoryVerifier.factory.createSocket();
-
- if (localSocket == null) {
- throw new IOException("could not initialize ssl socket");
- }
-
- SSLSocketHelper.setSecurity((SSLSocket) localSocket);
- SSLSocketHelper.setHostname((SSLSocket) localSocket, account.getServer());
- SSLSocketHelper.setApplicationProtocol((SSLSocket) localSocket, "xmpp-client");
+ localSocket = new Socket();
+ localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
- localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
-
- if (!tlsFactoryVerifier.verifier.verify(account.getServer(), verifiedHostname, ((SSLSocket) localSocket).getSession())) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed");
- FileBackend.close(localSocket);
- throw new StateChangingException(Account.State.TLS_ERROR);
- }
+ if (features.encryptionEnabled) {
+ localSocket = upgradeSocketToTls(localSocket);
}
+
localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
if (startXmpp(localSocket)) {
localSocket.setSoTimeout(0); //reset to 0; once the connection is established we don’t want this
@@ -410,6 +403,8 @@ public class XmppConnection implements Runnable {
this.changeStatus(e.state);
} catch (final UnknownHostException e) {
this.changeStatus(Account.State.SERVER_NOT_FOUND);
+ } catch (final SocksSocketFactory.HostNotFoundException e) {
+ this.changeStatus(Account.State.SERVER_NOT_FOUND);
} catch (final ConnectException e) {
this.changeStatus(Account.State.SERVER_NOT_FOUND);
} catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
@@ -834,48 +829,41 @@ public class XmppConnection implements Runnable {
private void switchOverToTls() throws XmlPullParserException, IOException {
tagReader.readTag();
- try {
- final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
- final InetAddress address = socket == null ? null : socket.getInetAddress();
-
- if (address == null) {
- throw new IOException("could not setup ssl");
- }
-
- final SSLSocket sslSocket = (SSLSocket) tlsFactoryVerifier.factory.createSocket(socket, address.getHostAddress(), socket.getPort(), true);
-
- if (sslSocket == null) {
- throw new IOException("could not initialize ssl socket");
- }
-
- SSLSocketHelper.setSecurity(sslSocket);
- SSLSocketHelper.setHostname(sslSocket, account.getServer());
- SSLSocketHelper.setApplicationProtocol(sslSocket, "xmpp-client");
+ final Socket socket = this.socket;
+ final SSLSocket sslSocket = upgradeSocketToTls(socket);
+ tagReader.setInputStream(sslSocket.getInputStream());
+ tagWriter.setOutputStream(sslSocket.getOutputStream());
+ sendStartStream();
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS connection established");
+ features.encryptionEnabled = true;
+ final Tag tag = tagReader.readTag();
+ if (tag != null && tag.isStart("stream")) {
+ SSLSocketHelper.log(account, sslSocket);
+ processStream();
+ } else {
+ throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
+ }
+ sslSocket.close();
+ }
- if (!tlsFactoryVerifier.verifier.verify(account.getServer(), this.verifiedHostname, sslSocket.getSession())) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed");
- throw new StateChangingException(Account.State.TLS_ERROR);
- }
- tagReader.setInputStream(sslSocket.getInputStream());
- tagWriter.setOutputStream(sslSocket.getOutputStream());
- sendStartStream();
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS connection established");
- features.encryptionEnabled = true;
- final Tag tag = tagReader.readTag();
- if (tag != null && tag.isStart("stream")) {
- SSLSocketHelper.log(account, sslSocket);
- processStream();
- } else {
- throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
- }
- sslSocket.close();
- } catch (final NoSuchAlgorithmException e1) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed");
+ private SSLSocket upgradeSocketToTls(final Socket socket) throws IOException {
+ final TlsFactoryVerifier tlsFactoryVerifier;
+ try {
+ tlsFactoryVerifier = getTlsFactoryVerifier();
+ } catch (final NoSuchAlgorithmException | KeyManagementException e) {
throw new StateChangingException(Account.State.TLS_ERROR);
- } catch (final KeyManagementException e1) {
+ }
+ final InetAddress address = socket.getInetAddress();
+ final SSLSocket sslSocket = (SSLSocket) tlsFactoryVerifier.factory.createSocket(socket, address.getHostAddress(), socket.getPort(), true);
+ SSLSocketHelper.setSecurity(sslSocket);
+ SSLSocketHelper.setHostname(sslSocket, account.getServer());
+ SSLSocketHelper.setApplicationProtocol(sslSocket, "xmpp-client");
+ if (!tlsFactoryVerifier.verifier.verify(account.getServer(), this.verifiedHostname, sslSocket.getSession())) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed");
+ FileBackend.close(sslSocket);
throw new StateChangingException(Account.State.TLS_ERROR);
}
+ return sslSocket;
}
private void processStreamFeatures(final Tag currentTag) throws XmlPullParserException, IOException {