From 496f531e2ef2cad5ff4dfb01ef0afe87c8b6b5c3 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 08:01:47 +0200 Subject: [PATCH 1/7] modified clearIqCallbacks into 2-step process --- .../siacs/conversations/parser/IqParser.java | 12 ++++----- .../eu/siacs/conversations/xml/Element.java | 5 ++-- .../conversations/xmpp/XmppConnection.java | 25 +++++++++++-------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index e74cb65c0..4488eed88 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -236,7 +236,9 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { + if (packet.getType() == IqPacket.TYPE.ERROR) { + return; + } else if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { final Element query = packet.findChild("query"); // If this is in response to a query for the whole roster: if (packet.getType() == IqPacket.TYPE.RESULT) { @@ -306,15 +308,13 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); mXmppConnectionService.sendIqPacket(account, response, null); } else { - if ((packet.getType() == IqPacket.TYPE.GET) - || (packet.getType() == IqPacket.TYPE.SET)) { + if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) { final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); final Element error = response.addChild("error"); error.setAttribute("type", "cancel"); - error.addChild("feature-not-implemented", - "urn:ietf:params:xml:ns:xmpp-stanzas"); + error.addChild("feature-not-implemented","urn:ietf:params:xml:ns:xmpp-stanzas"); account.getXmppConnection().sendIqPacket(response, null); - } + } } } diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index dc5a68f6c..7b4937b26 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -69,10 +69,9 @@ public class Element { public Element findChild(String name, String xmlns) { for (Element child : this.children) { - if (child.getName().equals(name) - && (child.getAttribute("xmlns").equals(xmlns))) { + if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) { return child; - } + } } return null; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 17b3c3ffb..e75cbb95a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1,13 +1,10 @@ package eu.siacs.conversations.xmpp; -import android.content.Context; -import android.content.SharedPreferences; import android.os.Bundle; import android.os.Parcelable; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; -import android.preference.PreferenceManager; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -37,7 +34,6 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import javax.net.ssl.HostnameVerifier; @@ -103,7 +99,7 @@ public class XmppConnection implements Runnable { private long lastConnect = 0; private long lastSessionStarted = 0; private int attempt = 0; - private final Map> packetCallbacks = new Hashtable<>(); + private final Hashtable> packetCallbacks = new Hashtable<>(); private OnPresencePacketReceived presenceListener = null; private OnJinglePacketReceived jingleListener = null; private OnIqPacketReceived unregisteredIqListener = null; @@ -727,9 +723,11 @@ public class XmppConnection implements Runnable { sendPostBindInitialization(); } } else { + Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure"); disconnect(true); } } else { + Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure"); disconnect(true); } } @@ -737,15 +735,19 @@ public class XmppConnection implements Runnable { } private void clearIqCallbacks() { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing iq iq callbacks"); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing "+this.packetCallbacks.size()+" iq callbacks"); final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.ERROR); + final ArrayList callbacks = new ArrayList<>(); synchronized (this.packetCallbacks) { - Iterator>> iterator = this.packetCallbacks.entrySet().iterator(); + final Iterator> iterator = this.packetCallbacks.values().iterator(); while (iterator.hasNext()) { - Entry> entry = iterator.next(); - entry.getValue().second.onIqPacketReceived(account, failurePacket); - iterator.remove(); + Pair entry = iterator.next(); + callbacks.add(entry.second); } + this.packetCallbacks.clear(); + } + for(OnIqPacketReceived callback : callbacks) { + callback.onIqPacketReceived(account,failurePacket); } } @@ -758,6 +760,7 @@ public class XmppConnection implements Runnable { if (packet.getType() == IqPacket.TYPE.RESULT) { sendPostBindInitialization(); } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not init sessions"); disconnect(true); } } @@ -887,6 +890,8 @@ public class XmppConnection implements Runnable { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": switching resource due to conflict (" + account.getResource() + ")"); + } else if (streamError != null) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString()); } } From 1688b659654cb1f3f5d4e20e6e238aa15fe60c96 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 08:27:05 +0200 Subject: [PATCH 2/7] don't make subsequent iq request when original stanza returned an error --- .../services/XmppConnectionService.java | 43 +++++------ .../conversations/xmpp/XmppConnection.java | 75 +++++++++++-------- 2 files changed, 67 insertions(+), 51 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index b89de6284..4811665b8 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -871,28 +871,31 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final Element query = packet.query(); - final List bookmarks = new CopyOnWriteArrayList<>(); - final Element storage = query.findChild("storage", - "storage:bookmarks"); - if (storage != null) { - for (final Element item : storage.getChildren()) { - if (item.getName().equals("conference")) { - final Bookmark bookmark = Bookmark.parse(item, account); - bookmarks.add(bookmark); - Conversation conversation = find(bookmark); - if (conversation != null) { - conversation.setBookmark(bookmark); - } else if (bookmark.autojoin() && bookmark.getJid() != null) { - conversation = findOrCreateConversation( - account, bookmark.getJid(), true); - conversation.setBookmark(bookmark); - joinMuc(conversation); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final Element query = packet.query(); + final List bookmarks = new CopyOnWriteArrayList<>(); + final Element storage = query.findChild("storage", "storage:bookmarks"); + if (storage != null) { + for (final Element item : storage.getChildren()) { + if (item.getName().equals("conference")) { + final Bookmark bookmark = Bookmark.parse(item, account); + bookmarks.add(bookmark); + Conversation conversation = find(bookmark); + if (conversation != null) { + conversation.setBookmark(bookmark); + } else if (bookmark.autojoin() && bookmark.getJid() != null) { + conversation = findOrCreateConversation( + account, bookmark.getJid(), true); + conversation.setBookmark(bookmark); + joinMuc(conversation); + } } } } + account.setBookmarks(bookmarks); + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fetch bookmarks"); } - account.setBookmarks(bookmarks); } }; sendIqPacket(account, iqPacket, callback); @@ -1955,10 +1958,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final IqPacket packet = XmppConnectionService.this.mIqGenerator .publishAvatarMetadata(avatar); sendIqPacket(account, packet, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, - IqPacket result) { + public void onIqPacketReceived(Account account, IqPacket result) { if (result.getType() == IqPacket.TYPE.RESULT) { if (account.setAvatar(avatar.getFilename())) { getAvatarService().clear(account); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index e75cbb95a..9063cca4a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -414,9 +414,12 @@ public class XmppConnection implements Runnable { this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() - + ": online with resource " + account.getResource()); - changeStatus(Account.State.ONLINE); + if (packet.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": online with resource " + account.getResource()); + changeStatus(Account.State.ONLINE); + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": initial ping failed"); + } } }); } @@ -656,8 +659,8 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final Element instructions = packet.query().findChild("instructions"); - if (packet.query().hasChild("username") + if (packet.getType() == IqPacket.TYPE.RESULT + && packet.query().hasChild("username") && (packet.query().hasChild("password"))) { final IqPacket register = new IqPacket(IqPacket.TYPE.SET); final Element username = new Element("username").setContent(account.getUsername()); @@ -684,6 +687,7 @@ public class XmppConnection implements Runnable { } }); } else { + final Element instructions = packet.query().findChild("instructions"); changeStatus(Account.State.REGISTRATION_FAILED); disconnect(true); Log.d(Config.LOGTAG, account.getJid().toBareJid() @@ -735,10 +739,13 @@ public class XmppConnection implements Runnable { } private void clearIqCallbacks() { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing "+this.packetCallbacks.size()+" iq callbacks"); final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.ERROR); final ArrayList callbacks = new ArrayList<>(); synchronized (this.packetCallbacks) { + if (this.packetCallbacks.size() == 0) { + return; + } + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing "+this.packetCallbacks.size()+" iq callbacks"); final Iterator> iterator = this.packetCallbacks.values().iterator(); while (iterator.hasNext()) { Pair entry = iterator.next(); @@ -749,6 +756,7 @@ public class XmppConnection implements Runnable { for(OnIqPacketReceived callback : callbacks) { callback.onIqPacketReceived(account,failurePacket); } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": done clearing iq callbacks"); } private void sendStartSession() { @@ -760,7 +768,7 @@ public class XmppConnection implements Runnable { if (packet.getType() == IqPacket.TYPE.RESULT) { sendPostBindInitialization(); } else { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not init sessions"); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions"); disconnect(true); } } @@ -805,26 +813,29 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final List elements = packet.query().getChildren(); - final Info info = new Info(); - for (final Element element : elements) { - if (element.getName().equals("identity")) { - String type = element.getAttribute("type"); - String category = element.getAttribute("category"); - if (type != null && category != null) { - info.identities.add(new Pair<>(category,type)); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final List elements = packet.query().getChildren(); + final Info info = new Info(); + for (final Element element : elements) { + if (element.getName().equals("identity")) { + String type = element.getAttribute("type"); + String category = element.getAttribute("category"); + if (type != null && category != null) { + info.identities.add(new Pair<>(category, type)); + } + } else if (element.getName().equals("feature")) { + info.features.add(element.getAttribute("var")); } - } else if (element.getName().equals("feature")) { - info.features.add(element.getAttribute("var")); } - } - disco.put(jid, info); - - if (account.getServer().equals(jid)) { - enableAdvancedStreamFeatures(); - for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) { - listener.onAdvancedStreamFeaturesAvailable(account); + disco.put(jid, info); + if (account.getServer().equals(jid)) { + enableAdvancedStreamFeatures(); + for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) { + listener.onAdvancedStreamFeaturesAvailable(account); + } } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not query disco info for "+jid.toString()); } } }); @@ -849,14 +860,18 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final List elements = packet.query().getChildren(); - for (final Element element : elements) { - if (element.getName().equals("item")) { - final Jid jid = element.getAttributeAsJid("jid"); - if (jid != null && !jid.equals(account.getServer())) { - sendServiceDiscoveryInfo(jid); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final List elements = packet.query().getChildren(); + for (final Element element : elements) { + if (element.getName().equals("item")) { + final Jid jid = element.getAttributeAsJid("jid"); + if (jid != null && !jid.equals(account.getServer())) { + sendServiceDiscoveryInfo(jid); + } } } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not query disco items of "+server); } } }); From 3d6fb9b21d41728a56e56b53901b080815805265 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 10:20:29 +0200 Subject: [PATCH 3/7] remove callbacks directly from iterator --- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 9063cca4a..ae11a3bfa 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -750,13 +750,13 @@ public class XmppConnection implements Runnable { while (iterator.hasNext()) { Pair entry = iterator.next(); callbacks.add(entry.second); + iterator.remove(); } - this.packetCallbacks.clear(); } for(OnIqPacketReceived callback : callbacks) { callback.onIqPacketReceived(account,failurePacket); } - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": done clearing iq callbacks"); + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": done clearing iq callbacks. "+this.packetCallbacks.size()+" left"); } private void sendStartSession() { From c0502c2165305a0370bc16f3a847ec2760fe70b9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 23 Aug 2015 12:39:20 +0200 Subject: [PATCH 4/7] remove the READ_PHONE_STATE permission. --- src/main/AndroidManifest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 15d5bc255..7f07a39c7 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -15,6 +15,8 @@ + + Date: Sun, 23 Aug 2015 13:23:10 +0200 Subject: [PATCH 5/7] Add error handling to OMEMO PEP code Log received errors and abort processing --- .../crypto/axolotl/AxolotlService.java | 253 ++++++++++-------- 1 file changed, 134 insertions(+), 119 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index f3775b793..d700b644b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -307,21 +307,25 @@ public class AxolotlService { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Element item = mXmppConnectionService.getIqParser().getItem(packet); - Set deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); - if (deviceIds == null) { - deviceIds = new HashSet(); - } - if (!deviceIds.contains(getOwnDeviceId())) { - deviceIds.add(getOwnDeviceId()); - IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish); - mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - // TODO: implement this! - } - }); + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element item = mXmppConnectionService.getIqParser().getItem(packet); + Set deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); + if (deviceIds == null) { + deviceIds = new HashSet(); + } + if (!deviceIds.contains(getOwnDeviceId())) { + deviceIds.add(getOwnDeviceId()); + IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish); + mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + // TODO: implement this! + } + }); + } + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing device ID:" + packet.findChild("error")); } } }); @@ -332,88 +336,92 @@ public class AxolotlService { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet); - Map keys = mXmppConnectionService.getIqParser().preKeyPublics(packet); - boolean flush = false; - if (bundle == null) { - Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet); - bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null); - flush = true; - } - if (keys == null) { - Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet); - } - try { - boolean changed = false; - // Validate IdentityKey - IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair(); - if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP."); - changed = true; + if (packet.getType() == IqPacket.TYPE.RESULT) { + PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet); + Map keys = mXmppConnectionService.getIqParser().preKeyPublics(packet); + boolean flush = false; + if (bundle == null) { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet); + bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null); + flush = true; + } + if (keys == null) { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet); } - - // Validate signedPreKeyRecord + ID - SignedPreKeyRecord signedPreKeyRecord; - int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size(); try { - signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId()); - if (flush - || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) - || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) { + boolean changed = false; + // Validate IdentityKey + IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair(); + if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) { + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP."); + changed = true; + } + + // Validate signedPreKeyRecord + ID + SignedPreKeyRecord signedPreKeyRecord; + int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size(); + try { + signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId()); + if (flush + || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) + || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) { + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); + signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); + axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); + changed = true; + } + } catch (InvalidKeyIdException e) { Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); changed = true; } - } catch (InvalidKeyIdException e) { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); - signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); - axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); - changed = true; - } - // Validate PreKeys - Set preKeyRecords = new HashSet<>(); - if (keys != null) { - for (Integer id : keys.keySet()) { - try { - PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id); - if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) { - preKeyRecords.add(preKeyRecord); + // Validate PreKeys + Set preKeyRecords = new HashSet<>(); + if (keys != null) { + for (Integer id : keys.keySet()) { + try { + PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id); + if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) { + preKeyRecords.add(preKeyRecord); + } + } catch (InvalidKeyIdException ignored) { } - } catch (InvalidKeyIdException ignored) { } } - } - int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size(); - if (newKeys > 0) { - List newRecords = KeyHelper.generatePreKeys( - axolotlStore.getCurrentPreKeyId() + 1, newKeys); - preKeyRecords.addAll(newRecords); - for (PreKeyRecord record : newRecords) { - axolotlStore.storePreKey(record.getId(), record); - } - changed = true; - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP."); - } - - - if (changed) { - IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( - signedPreKeyRecord, axolotlStore.getIdentityKeyPair().getPublicKey(), - preKeyRecords, getOwnDeviceId()); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": Bundle " + getOwnDeviceId() + " in PEP not current. Publishing: " + publish); - mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - // TODO: implement this! - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Published bundle, got: " + packet); + int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size(); + if (newKeys > 0) { + List newRecords = KeyHelper.generatePreKeys( + axolotlStore.getCurrentPreKeyId() + 1, newKeys); + preKeyRecords.addAll(newRecords); + for (PreKeyRecord record : newRecords) { + axolotlStore.storePreKey(record.getId(), record); } - }); + changed = true; + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP."); + } + + + if (changed) { + IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( + signedPreKeyRecord, axolotlStore.getIdentityKeyPair().getPublicKey(), + preKeyRecords, getOwnDeviceId()); + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": Bundle " + getOwnDeviceId() + " in PEP not current. Publishing: " + publish); + mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + // TODO: implement this! + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Published bundle, got: " + packet); + } + }); + } + } catch (InvalidKeyException e) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage()); + return; } - } catch (InvalidKeyException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage()); - return; + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing Bundle:" + packet.findChild("error")); } } }); @@ -453,45 +461,52 @@ public class AxolotlService { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); - final IqParser parser = mXmppConnectionService.getIqParser(); - final List preKeyBundleList = parser.preKeys(packet); - final PreKeyBundle bundle = parser.bundle(packet); - if (preKeyBundleList.isEmpty() || bundle == null) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); + if (packet.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); + final IqParser parser = mXmppConnectionService.getIqParser(); + final List preKeyBundleList = parser.preKeys(packet); + final PreKeyBundle bundle = parser.bundle(packet); + if (preKeyBundleList.isEmpty() || bundle == null) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); + fetchStatusMap.put(address, FetchStatus.ERROR); + finish(); + return; + } + Random random = new Random(); + final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); + if (preKey == null) { + //should never happen + fetchStatusMap.put(address, FetchStatus.ERROR); + finish(); + return; + } + + final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), + preKey.getPreKeyId(), preKey.getPreKey(), + bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), + bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); + + axolotlStore.saveIdentity(address.getName(), bundle.getIdentityKey()); + + try { + SessionBuilder builder = new SessionBuilder(axolotlStore, address); + builder.process(preKeyBundle); + XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", "")); + sessions.put(address, session); + fetchStatusMap.put(address, FetchStatus.SUCCESS); + } catch (UntrustedIdentityException | InvalidKeyException e) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " + + e.getClass().getName() + ", " + e.getMessage()); + fetchStatusMap.put(address, FetchStatus.ERROR); + } + + finish(); + } else { fetchStatusMap.put(address, FetchStatus.ERROR); + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error")); finish(); return; } - Random random = new Random(); - final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); - if (preKey == null) { - //should never happen - fetchStatusMap.put(address, FetchStatus.ERROR); - finish(); - return; - } - - final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), - preKey.getPreKeyId(), preKey.getPreKey(), - bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), - bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); - - axolotlStore.saveIdentity(address.getName(), bundle.getIdentityKey()); - - try { - SessionBuilder builder = new SessionBuilder(axolotlStore, address); - builder.process(preKeyBundle); - XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", "")); - sessions.put(address, session); - fetchStatusMap.put(address, FetchStatus.SUCCESS); - } catch (UntrustedIdentityException | InvalidKeyException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " - + e.getClass().getName() + ", " + e.getMessage()); - fetchStatusMap.put(address, FetchStatus.ERROR); - } - - finish(); } }); } catch (InvalidJidException e) { From 96c6c793b3791ab2b0cfa94d945097da005ce18c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 13:25:04 +0200 Subject: [PATCH 6/7] version bump to 1.6.1 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0537d3961..252aedbe3 100644 --- a/build.gradle +++ b/build.gradle @@ -48,8 +48,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 84 - versionName "1.6.0" + versionCode 85 + versionName "1.6.1" } compileOptions { From 560e63564dfb4608de6615b1388e6651d5ee93ba Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 23 Aug 2015 13:29:55 +0200 Subject: [PATCH 7/7] added changelog for 1.6.1 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 644137094..0f081319e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ###Changelog +####Version 1.6.1 +* fixed crashes + ####Version 1.6.0 * new multi-end-to-multi-end encryption method * redesigned chat bubbles