mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Improve behavior of trust command
- Remove all other identities for the same number Fixes #540
This commit is contained in:
parent
8249f852f9
commit
4860caef63
4 changed files with 70 additions and 55 deletions
|
@ -156,6 +156,7 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
|
import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
|
||||||
|
@ -1211,10 +1212,12 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync());
|
messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync());
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
account.getSignalProtocolStore()
|
if (e.getIdentityKey() != null) {
|
||||||
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
account.getSignalProtocolStore()
|
||||||
e.getIdentityKey(),
|
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
||||||
TrustLevel.UNTRUSTED);
|
e.getIdentityKey(),
|
||||||
|
TrustLevel.UNTRUSTED);
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1296,10 +1299,12 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
return new Pair<>(timestamp, result);
|
return new Pair<>(timestamp, result);
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
account.getSignalProtocolStore()
|
if (e.getIdentityKey() != null) {
|
||||||
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
account.getSignalProtocolStore()
|
||||||
e.getIdentityKey(),
|
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
||||||
TrustLevel.UNTRUSTED);
|
e.getIdentityKey(),
|
||||||
|
TrustLevel.UNTRUSTED);
|
||||||
|
}
|
||||||
return new Pair<>(timestamp, List.of());
|
return new Pair<>(timestamp, List.of());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1369,10 +1374,12 @@ public class Manager implements Closeable {
|
||||||
false,
|
false,
|
||||||
System.currentTimeMillis() - startTime);
|
System.currentTimeMillis() - startTime);
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
account.getSignalProtocolStore()
|
if (e.getIdentityKey() != null) {
|
||||||
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
account.getSignalProtocolStore()
|
||||||
e.getIdentityKey(),
|
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
||||||
TrustLevel.UNTRUSTED);
|
e.getIdentityKey(),
|
||||||
|
TrustLevel.UNTRUSTED);
|
||||||
|
}
|
||||||
return SendMessageResult.identityFailure(recipient, e.getIdentityKey());
|
return SendMessageResult.identityFailure(recipient, e.getIdentityKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1385,10 +1392,12 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message);
|
return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message);
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
account.getSignalProtocolStore()
|
if (e.getIdentityKey() != null) {
|
||||||
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
account.getSignalProtocolStore()
|
||||||
e.getIdentityKey(),
|
.saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
|
||||||
TrustLevel.UNTRUSTED);
|
e.getIdentityKey(),
|
||||||
|
TrustLevel.UNTRUSTED);
|
||||||
|
}
|
||||||
return SendMessageResult.identityFailure(address, e.getIdentityKey());
|
return SendMessageResult.identityFailure(address, e.getIdentityKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2388,26 +2397,7 @@ public class Manager implements Closeable {
|
||||||
*/
|
*/
|
||||||
public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException {
|
public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException {
|
||||||
var address = canonicalizeAndResolveSignalServiceAddress(name);
|
var address = canonicalizeAndResolveSignalServiceAddress(name);
|
||||||
var ids = account.getSignalProtocolStore().getIdentities(address);
|
return trustIdentity(address, (identityKey) -> Arrays.equals(identityKey.serialize(), fingerprint));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2418,26 +2408,46 @@ public class Manager implements Closeable {
|
||||||
*/
|
*/
|
||||||
public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException {
|
public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException {
|
||||||
var address = canonicalizeAndResolveSignalServiceAddress(name);
|
var address = canonicalizeAndResolveSignalServiceAddress(name);
|
||||||
|
return trustIdentity(address, (identityKey) -> safetyNumber.equals(computeSafetyNumber(address, identityKey)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean trustIdentity(SignalServiceAddress address, Function<IdentityKey, Boolean> verifier) {
|
||||||
var ids = account.getSignalProtocolStore().getIdentities(address);
|
var ids = account.getSignalProtocolStore().getIdentities(address);
|
||||||
if (ids == null) {
|
if (ids == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentityInfo foundIdentity = null;
|
||||||
|
|
||||||
for (var id : ids) {
|
for (var id : ids) {
|
||||||
if (!safetyNumber.equals(computeSafetyNumber(address, id.getIdentityKey()))) {
|
if (verifier.apply(id.getIdentityKey())) {
|
||||||
|
foundIdentity = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
account.getSignalProtocolStore().removeIdentity(address, id.getIdentityKey());
|
||||||
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;
|
|
||||||
|
account.save();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,13 +13,6 @@ public class IdentityInfo {
|
||||||
TrustLevel trustLevel;
|
TrustLevel trustLevel;
|
||||||
Date added;
|
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) {
|
IdentityInfo(SignalServiceAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.identityKey = identityKey;
|
this.identityKey = identityKey;
|
||||||
|
|
|
@ -125,6 +125,10 @@ public class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
identities.add(new IdentityInfo(serviceAddress, identityKey, trustLevel, new Date()));
|
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
|
@Override
|
||||||
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
|
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
|
||||||
// TODO implement possibility for different handling of incoming/outgoing trust decisions
|
// 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;
|
return trustOnFirstUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,10 @@ public class JsonSignalProtocolStore implements SignalServiceProtocolStore {
|
||||||
identityKeyStore.setIdentityTrustLevel(serviceAddress, identityKey, trustLevel);
|
identityKeyStore.setIdentityTrustLevel(serviceAddress, identityKey, trustLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeIdentity(SignalServiceAddress serviceAddress, IdentityKey identityKey) {
|
||||||
|
identityKeyStore.removeIdentity(serviceAddress, identityKey);
|
||||||
|
}
|
||||||
|
|
||||||
public List<IdentityInfo> getIdentities() {
|
public List<IdentityInfo> getIdentities() {
|
||||||
return identityKeyStore.getIdentities();
|
return identityKeyStore.getIdentities();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue