aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp/XmppConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs/conversations/xmpp/XmppConnection.java')
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java81
1 files changed, 65 insertions, 16 deletions
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index 43614f50..0252d80e 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -10,8 +10,10 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
@@ -26,15 +28,19 @@ import org.xmlpull.v1.XmlPullParserException;
import de.duenndns.ssl.MemorizingTrustManager;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
+import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseArray;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.ui.StartConversationActivity;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.DNSHelper;
import eu.siacs.conversations.utils.zlib.ZLibOutputStream;
@@ -80,6 +86,7 @@ public class XmppConnection implements Runnable {
private SparseArray<String> messageReceipts = new SparseArray<String>();
private boolean usingCompression = false;
+ private boolean usingEncryption = false;
private int stanzasReceived = 0;
private int stanzasSent = 0;
@@ -104,6 +111,7 @@ public class XmppConnection implements Runnable {
private OnBindListener bindListener = null;
private OnMessageAcknowledged acknowledgedListener = null;
private MemorizingTrustManager mMemorizingTrustManager;
+ private final Context applicationContext;
public XmppConnection(Account account, XmppConnectionService service) {
this.mRandom = service.getRNG();
@@ -112,6 +120,7 @@ public class XmppConnection implements Runnable {
this.wakeLock = service.getPowerManager().newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, account.getJid());
tagWriter = new TagWriter();
+ applicationContext = service.getApplicationContext();
}
protected void changeStatus(int nextStatus) {
@@ -135,6 +144,7 @@ public class XmppConnection implements Runnable {
protected void connect() {
Log.d(Config.LOGTAG, account.getJid() + ": connecting");
usingCompression = false;
+ usingEncryption = false;
lastConnect = SystemClock.elapsedRealtime();
lastPingSent = SystemClock.elapsedRealtime();
this.attempt++;
@@ -161,10 +171,23 @@ public class XmppConnection implements Runnable {
+ "[" + srvIpServer + "]:" + srvRecordPort);
socket = new Socket(srvIpServer, srvRecordPort);
} else {
- Log.d(Config.LOGTAG, account.getJid()
- + ": using values from dns " + srvRecordServer
- + ":" + srvRecordPort);
- socket = new Socket(srvRecordServer, srvRecordPort);
+ boolean socketError = true;
+ int srvIndex = 0;
+ while (socketError && namePort.containsKey("name" + srvIndex)){
+ try {
+ srvRecordServer = namePort.getString("name" + srvIndex);
+ srvRecordPort = namePort.getInt("port" + srvIndex);
+ Log.d(Config.LOGTAG, account.getJid()
+ + ": using values from dns " + srvRecordServer
+ + ":" + srvRecordPort);
+ socket = new Socket(srvRecordServer, srvRecordPort);
+ socketError = false;
+ } catch (UnknownHostException e) {
+ srvIndex++;
+ } catch (IOException e) {
+ srvIndex++;
+ }
+ }
}
} else if (namePort.containsKey("error")
&& "nosrv".equals(namePort.getString("error", null))) {
@@ -362,13 +385,13 @@ public class XmppConnection implements Runnable {
iq.addChild("ping", "urn:xmpp:ping");
this.sendIqPacket(iq, new OnIqPacketReceived() {
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- Log.d(Config.LOGTAG, account.getJid()
- + ": online with resource " + account.getResource());
- changeStatus(Account.STATUS_ONLINE);
- }
- });
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Log.d(Config.LOGTAG, account.getJid()
+ + ": online with resource " + account.getResource());
+ changeStatus(Account.STATUS_ONLINE);
+ }
+ });
}
private Element processPacket(Tag currentTag, int packetType)
@@ -504,6 +527,14 @@ public class XmppConnection implements Runnable {
tagWriter.writeTag(startTLS);
}
+ private SharedPreferences getPreferences() {
+ return PreferenceManager.getDefaultSharedPreferences(applicationContext);
+ }
+
+ private boolean enableLegacySSL() {
+ return getPreferences().getBoolean("enable_legacy_ssl", false);
+ }
+
private void switchOverToTls(Tag currentTag) throws XmlPullParserException,
IOException {
tagReader.readTag();
@@ -520,6 +551,21 @@ public class XmppConnection implements Runnable {
socket.getInetAddress().getHostAddress(), socket.getPort(),
true);
+ // Support all protocols except legacy SSL.
+ // The min SDK version prevents us having to worry about SSLv2. In future, this may be
+ // true of SSLv3 as well.
+ final String[] supportProtocols;
+ if (enableLegacySSL()) {
+ supportProtocols = sslSocket.getSupportedProtocols();
+ } else {
+ final List<String> supportedProtocols = new LinkedList<String>(Arrays.asList(
+ sslSocket.getSupportedProtocols()));
+ supportedProtocols.remove("SSLv3");
+ supportProtocols = new String[supportedProtocols.size()];
+ supportedProtocols.toArray(supportProtocols);
+ }
+ sslSocket.setEnabledProtocols(supportProtocols);
+
if (verifier != null
&& !verifier.verify(account.getServer(),
sslSocket.getSession())) {
@@ -533,6 +579,7 @@ public class XmppConnection implements Runnable {
sendStartStream();
Log.d(Config.LOGTAG, account.getJid()
+ ": TLS connection established");
+ usingEncryption = true;
processStream(tagReader.readTag());
sslSocket.close();
} catch (NoSuchAlgorithmException e1) {
@@ -562,20 +609,19 @@ public class XmppConnection implements Runnable {
private void processStreamFeatures(Tag currentTag)
throws XmlPullParserException, IOException {
this.streamFeatures = tagReader.readElement(currentTag);
- if (this.streamFeatures.hasChild("starttls")
- && account.isOptionSet(Account.OPTION_USETLS)) {
+ if (this.streamFeatures.hasChild("starttls") && !usingEncryption) {
sendStartTLS();
} else if (compressionAvailable()) {
sendCompressionZlib();
} else if (this.streamFeatures.hasChild("register")
- && (account.isOptionSet(Account.OPTION_REGISTER))) {
+ && account.isOptionSet(Account.OPTION_REGISTER) && usingEncryption) {
sendRegistryRequest();
} else if (!this.streamFeatures.hasChild("register")
- && (account.isOptionSet(Account.OPTION_REGISTER))) {
+ && account.isOptionSet(Account.OPTION_REGISTER)) {
changeStatus(Account.STATUS_REGISTRATION_NOT_SUPPORTED);
disconnect(true);
} else if (this.streamFeatures.hasChild("mechanisms")
- && shouldAuthenticate) {
+ && shouldAuthenticate && usingEncryption) {
List<String> mechanisms = extractMechanisms(streamFeatures
.findChild("mechanisms"));
if (mechanisms.contains("PLAIN")) {
@@ -591,6 +637,9 @@ public class XmppConnection implements Runnable {
this.tagWriter.writeStanzaAsync(resume);
} else if (this.streamFeatures.hasChild("bind") && shouldBind) {
sendBindRequest();
+ } else {
+ Log.d(Config.LOGTAG,account.getJid()+": incompatible server. disconnecting");
+ disconnect(true);
}
}