From 1cf0241aed94015f5c5fc523b756cbbd5a797de7 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 20 Nov 2016 17:42:16 +0100 Subject: remove omemo devices from annoucement after 7 days of inactivity --- src/main/java/de/pixart/messenger/Config.java | 7 +- .../messenger/crypto/axolotl/AxolotlService.java | 74 +++++++++++++++------- .../crypto/axolotl/FingerprintStatus.java | 4 ++ .../messenger/persistance/DatabaseBackend.java | 14 ++++ 4 files changed, 72 insertions(+), 27 deletions(-) (limited to 'src/main/java/de/pixart/messenger') diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java index f44ab661b..13b3055bb 100644 --- a/src/main/java/de/pixart/messenger/Config.java +++ b/src/main/java/de/pixart/messenger/Config.java @@ -6,6 +6,8 @@ import de.pixart.messenger.xmpp.chatstate.ChatState; public final class Config { + public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; + private static final int UNENCRYPTED = 1; private static final int OPENPGP = 2; private static final int OTR = 4; @@ -79,8 +81,6 @@ public final class Config { public static final int VIDEO_BITRATE = 500000; public static final int VIDEO_MAX_SIZE = 10485760; //10 MiB - public static final int FILE_MAX_SIZE = 1048576; //1 MiB - public static final int DEFAULT_ZOOM = 15; //for locations public static final int MESSAGE_MERGE_WINDOW = 20; @@ -90,6 +90,8 @@ public final class Config { public static final int REFRESH_UI_INTERVAL = 1000; + public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY; // delete old OMEMO devices after 7 days od inactivity + public static final int MAX_DISPLAY_MESSAGE_CHARS = 4096; public static final boolean ExportLogs = true; // automatically export logs @@ -115,7 +117,6 @@ public final class Config { public static final boolean PARSE_REAL_JID_FROM_MUC_MAM = false; //dangerous if server doesn’t filter - public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; public static final int MAM_MAX_MESSAGES = 500; diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java b/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java index 8c9b5a7bb..8a38ce20d 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java +++ b/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import de.pixart.messenger.Config; import de.pixart.messenger.entities.Account; @@ -75,6 +76,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private final SerialSingleThreadExecutor executor; private int numPublishTriesOnEmptyPep = 0; private boolean pepBroken = false; + private AtomicBoolean ownPushPending = new AtomicBoolean(false); @Override public void onAdvancedStreamFeaturesAvailable(Account account) { @@ -302,15 +304,15 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public Collection findOwnSessions() { AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid()); ArrayList s = new ArrayList<>(this.sessions.getAll(ownAddress).values()); - Collections.sort(s); - return s; + Collections.sort(s); + return s; } public Collection findSessionsForContact(Contact contact) { AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); ArrayList s = new ArrayList<>(this.sessions.getAll(contactAddress).values()); - Collections.sort(s); - return s; + Collections.sort(s); + return s; } private Set findSessionsForConversation(Conversation conversation) { @@ -354,23 +356,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public void registerDevices(final Jid jid, @NonNull final Set deviceIds) { - if (jid.toBareJid().equals(account.getJid().toBareJid())) { - if (!deviceIds.isEmpty()) { - Log.d(Config.LOGTAG, getLogprefix(account) + "Received non-empty own device list. Resetting publish attempts and pepBroken status."); - pepBroken = false; - numPublishTriesOnEmptyPep = 0; - } - if (deviceIds.contains(getOwnDeviceId())) { - deviceIds.remove(getOwnDeviceId()); - } else { - publishOwnDeviceId(deviceIds); - } - for (Integer deviceId : deviceIds) { - AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); - if (sessions.get(ownDeviceAddress) == null) { - buildSessionFromPEP(ownDeviceAddress); - } - } + boolean me = jid.toBareJid().equals(account.getJid().toBareJid()); + if (me && ownPushPending.getAndSet(false)) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": ignoring own device update because of pending push"); + return; + } + boolean needsPublishing = me && !deviceIds.contains(getOwnDeviceId()); + if (me) { + deviceIds.remove(getOwnDeviceId()); } Set expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString())); expiredDevices.removeAll(deviceIds); @@ -389,10 +382,25 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { XmppAxolotlSession session = sessions.get(address); if (session != null && session.getFingerprint() != null) { if (!session.getTrust().isActive()) { + Log.d(Config.LOGTAG,"reactivating device with fingprint "+session.getFingerprint()); session.setTrust(session.getTrust().toActive()); } } } + if (me) { + if (Config.OMEMO_AUTO_EXPIRY != 0) { + needsPublishing |= deviceIds.removeAll(getExpiredDevices()); + } + for (Integer deviceId : deviceIds) { + AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); + if (sessions.get(ownDeviceAddress) == null) { + buildSessionFromPEP(ownDeviceAddress); + } + } + if (needsPublishing) { + publishOwnDeviceId(deviceIds); + } + } this.deviceIds.put(jid, deviceIds); mXmppConnectionService.keyStatusUpdated(null); } @@ -427,14 +435,30 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } else { Element item = mXmppConnectionService.getIqParser().getItem(packet); Set deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); - if (!deviceIds.contains(getOwnDeviceId())) { - publishOwnDeviceId(deviceIds); - } + registerDevices(account.getJid().toBareJid(),deviceIds); } } }); } + private Set getExpiredDevices() { + Set devices = new HashSet<>(); + for(XmppAxolotlSession session : findOwnSessions()) { + if (session.getTrust().isActive()) { + long diff = System.currentTimeMillis() - session.getTrust().getLastActivation(); + if (diff > Config.OMEMO_AUTO_EXPIRY) { + long lastMessageDiff = System.currentTimeMillis() - mXmppConnectionService.databaseBackend.getLastTimeFingerprintUsed(account,session.getFingerprint()); + if (lastMessageDiff > Config.OMEMO_AUTO_EXPIRY) { + devices.add(session.getRemoteAddress().getDeviceId()); + session.setTrust(session.getTrust().toInactive()); + Log.d(Config.LOGTAG, "added own device " + session.getFingerprint() + " to list of expired devices. Last message received "+(lastMessageDiff/1000)+"s ago"); + } + } + } + } + return devices; + } + public void publishOwnDeviceId(Set deviceIds) { Set deviceIdsCopy = new HashSet<>(deviceIds); if (!deviceIdsCopy.contains(getOwnDeviceId())) { @@ -453,9 +477,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } deviceIdsCopy.add(getOwnDeviceId()); IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIdsCopy); + ownPushPending.set(true); mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { + ownPushPending.set(false); if (packet.getType() == IqPacket.TYPE.ERROR) { pepBroken = true; Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing own device id" + packet.findChild("error")); diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/FingerprintStatus.java b/src/main/java/de/pixart/messenger/crypto/axolotl/FingerprintStatus.java index bffb94e1f..0614b759f 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/FingerprintStatus.java +++ b/src/main/java/de/pixart/messenger/crypto/axolotl/FingerprintStatus.java @@ -156,6 +156,10 @@ public class FingerprintStatus implements Comparable { } } + public long getLastActivation() { + return lastActivation; + } + public enum Trust { COMPROMISED, UNDECIDED, diff --git a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java index 03b71c226..25fb2aeef 100644 --- a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java +++ b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java @@ -786,6 +786,20 @@ public class DatabaseBackend extends SQLiteOpenHelper { } } + public long getLastTimeFingerprintUsed(Account account, String fingerprint) { + String SQL = "select messages.timeSent from accounts join conversations on accounts.uuid=conversations.accountUuid join messages on conversations.uuid=messages.conversationUuid where accounts.uuid=? and messages.axolotl_fingerprint=? order by messages.timesent desc limit 1"; + String[] args = {account.getUuid(), fingerprint}; + Cursor cursor = getReadableDatabase().rawQuery(SQL,args); + long time; + if (cursor.moveToFirst()) { + time = cursor.getLong(0); + } else { + time = 0; + } + cursor.close(); + return time; + } + public Pair getLastClearDate(Account account) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {Conversation.ATTRIBUTES}; -- cgit v1.2.3