From: AsamK Date: Thu, 25 Feb 2021 18:20:02 +0000 (+0100) Subject: Improve behavior of trust command X-Git-Tag: v0.8.1~9 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/4860caef63080c501e06418f1bca7030a7c7898d?ds=sidebyside Improve behavior of trust command - Remove all other identities for the same number Fixes #540 --- diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index caedf2f1..88335916 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -156,6 +156,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Function; import java.util.stream.Collectors; import static org.asamk.signal.manager.config.ServiceConfig.capabilities; @@ -1211,10 +1212,12 @@ public class Manager implements Closeable { try { messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync()); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } throw e; } } @@ -1296,10 +1299,12 @@ public class Manager implements Closeable { } return new Pair<>(timestamp, result); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return new Pair<>(timestamp, List.of()); } } else { @@ -1369,10 +1374,12 @@ public class Manager implements Closeable { false, System.currentTimeMillis() - startTime); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return SendMessageResult.identityFailure(recipient, e.getIdentityKey()); } } @@ -1385,10 +1392,12 @@ public class Manager implements Closeable { try { return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message); } catch (UntrustedIdentityException e) { - account.getSignalProtocolStore() - .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), - e.getIdentityKey(), - TrustLevel.UNTRUSTED); + if (e.getIdentityKey() != null) { + account.getSignalProtocolStore() + .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), + e.getIdentityKey(), + TrustLevel.UNTRUSTED); + } return SendMessageResult.identityFailure(address, e.getIdentityKey()); } } @@ -2388,26 +2397,7 @@ public class Manager implements Closeable { */ public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException { var address = canonicalizeAndResolveSignalServiceAddress(name); - var ids = account.getSignalProtocolStore().getIdentities(address); - if (ids == null) { - return false; - } - for (var id : ids) { - if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) { - continue; - } - - account.getSignalProtocolStore() - .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - try { - sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - } catch (IOException | UntrustedIdentityException e) { - logger.warn("Failed to send verification sync message: {}", e.getMessage()); - } - account.save(); - return true; - } - return false; + return trustIdentity(address, (identityKey) -> Arrays.equals(identityKey.serialize(), fingerprint)); } /** @@ -2418,26 +2408,46 @@ public class Manager implements Closeable { */ public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException { var address = canonicalizeAndResolveSignalServiceAddress(name); + return trustIdentity(address, (identityKey) -> safetyNumber.equals(computeSafetyNumber(address, identityKey))); + } + + private boolean trustIdentity(SignalServiceAddress address, Function verifier) { var ids = account.getSignalProtocolStore().getIdentities(address); if (ids == null) { return false; } + + IdentityInfo foundIdentity = null; + for (var id : ids) { - if (!safetyNumber.equals(computeSafetyNumber(address, id.getIdentityKey()))) { - continue; + if (verifier.apply(id.getIdentityKey())) { + foundIdentity = id; + break; } + } - account.getSignalProtocolStore() - .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - try { - sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); - } catch (IOException | UntrustedIdentityException e) { - logger.warn("Failed to send verification sync message: {}", e.getMessage()); + if (foundIdentity == null) { + return false; + } + + account.getSignalProtocolStore() + .setIdentityTrustLevel(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); + try { + sendVerifiedMessage(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); + } catch (IOException | UntrustedIdentityException e) { + logger.warn("Failed to send verification sync message: {}", e.getMessage()); + } + + // Successfully trusted the new identity, now remove all other identities for that number + for (var id : ids) { + if (id == foundIdentity) { + continue; } - account.save(); - return true; + account.getSignalProtocolStore().removeIdentity(address, id.getIdentityKey()); } - return false; + + account.save(); + return true; } /** diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java index d4af11f2..652bf524 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/IdentityInfo.java @@ -13,13 +13,6 @@ public class IdentityInfo { TrustLevel trustLevel; Date added; - public IdentityInfo(SignalServiceAddress address, IdentityKey identityKey, TrustLevel trustLevel) { - this.address = address; - this.identityKey = identityKey; - this.trustLevel = trustLevel; - this.added = new Date(); - } - IdentityInfo(SignalServiceAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) { this.address = address; this.identityKey = identityKey; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java index ed04e556..561138c6 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonIdentityKeyStore.java @@ -125,6 +125,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { identities.add(new IdentityInfo(serviceAddress, identityKey, trustLevel, new Date())); } + public void removeIdentity(SignalServiceAddress serviceAddress, IdentityKey identityKey) { + identities.removeIf(id -> id.address.matches(serviceAddress) && id.identityKey.equals(identityKey)); + } + @Override public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) { // TODO implement possibility for different handling of incoming/outgoing trust decisions @@ -143,6 +147,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { } } + if (!trustOnFirstUse) { + saveIdentity(resolveSignalServiceAddress(address.getName()), identityKey, TrustLevel.UNTRUSTED, null); + } + return trustOnFirstUse; } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java index 5a863b6e..d47f7a1a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/JsonSignalProtocolStore.java @@ -91,6 +91,10 @@ public class JsonSignalProtocolStore implements SignalServiceProtocolStore { identityKeyStore.setIdentityTrustLevel(serviceAddress, identityKey, trustLevel); } + public void removeIdentity(SignalServiceAddress serviceAddress, IdentityKey identityKey) { + identityKeyStore.removeIdentity(serviceAddress, identityKey); + } + public List getIdentities() { return identityKeyStore.getIdentities(); }