refactore trust enum to be FingerprintStatus class with trust and active
This commit is contained in:
parent
6da8b50d95
commit
05fc15be3d
|
@ -256,18 +256,18 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
return axolotlStore.getIdentityKeyPair().getPublicKey().getFingerprint().replaceAll("\\s", "");
|
||||
}
|
||||
|
||||
public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust) {
|
||||
return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toPreppedString(), trust);
|
||||
public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status) {
|
||||
return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toPreppedString(), status);
|
||||
}
|
||||
|
||||
public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust, Jid jid) {
|
||||
return axolotlStore.getContactKeysWithTrust(jid.toBareJid().toPreppedString(), trust);
|
||||
public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status, Jid jid) {
|
||||
return axolotlStore.getContactKeysWithTrust(jid.toBareJid().toPreppedString(), status);
|
||||
}
|
||||
|
||||
public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust, List<Jid> jids) {
|
||||
public Set<IdentityKey> getKeysWithTrust(FingerprintStatus status, List<Jid> jids) {
|
||||
Set<IdentityKey> keys = new HashSet<>();
|
||||
for(Jid jid : jids) {
|
||||
keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toPreppedString(), trust));
|
||||
keys.addAll(axolotlStore.getContactKeysWithTrust(jid.toPreppedString(), status));
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
@ -355,19 +355,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
return this.deviceIds.get(account.getJid().toBareJid());
|
||||
}
|
||||
|
||||
private void setTrustOnSessions(final Jid jid, @NonNull final Set<Integer> deviceIds,
|
||||
final XmppAxolotlSession.Trust from,
|
||||
final XmppAxolotlSession.Trust to) {
|
||||
for (Integer deviceId : deviceIds) {
|
||||
AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId);
|
||||
XmppAxolotlSession session = sessions.get(address);
|
||||
if (session != null && session.getFingerprint() != null
|
||||
&& session.getTrust() == from) {
|
||||
session.setTrust(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerDevices(final Jid jid, @NonNull final Set<Integer> deviceIds) {
|
||||
if (jid.toBareJid().equals(account.getJid().toBareJid())) {
|
||||
if (!deviceIds.isEmpty()) {
|
||||
|
@ -389,23 +376,25 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
}
|
||||
Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString()));
|
||||
expiredDevices.removeAll(deviceIds);
|
||||
setTrustOnSessions(jid, expiredDevices, XmppAxolotlSession.Trust.TRUSTED,
|
||||
XmppAxolotlSession.Trust.INACTIVE_TRUSTED);
|
||||
setTrustOnSessions(jid, expiredDevices, XmppAxolotlSession.Trust.TRUSTED_X509,
|
||||
XmppAxolotlSession.Trust.INACTIVE_TRUSTED_X509);
|
||||
setTrustOnSessions(jid, expiredDevices, XmppAxolotlSession.Trust.UNDECIDED,
|
||||
XmppAxolotlSession.Trust.INACTIVE_UNDECIDED);
|
||||
setTrustOnSessions(jid, expiredDevices, XmppAxolotlSession.Trust.UNTRUSTED,
|
||||
XmppAxolotlSession.Trust.INACTIVE_UNTRUSTED);
|
||||
for (Integer deviceId : expiredDevices) {
|
||||
AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId);
|
||||
XmppAxolotlSession session = sessions.get(address);
|
||||
if (session != null && session.getFingerprint() != null) {
|
||||
if (session.getTrust().isActive()) {
|
||||
session.setTrust(session.getTrust().toInactive());
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<Integer> newDevices = new HashSet<>(deviceIds);
|
||||
setTrustOnSessions(jid, newDevices, XmppAxolotlSession.Trust.INACTIVE_TRUSTED,
|
||||
XmppAxolotlSession.Trust.TRUSTED);
|
||||
setTrustOnSessions(jid, newDevices, XmppAxolotlSession.Trust.INACTIVE_TRUSTED_X509,
|
||||
XmppAxolotlSession.Trust.TRUSTED_X509);
|
||||
setTrustOnSessions(jid, newDevices, XmppAxolotlSession.Trust.INACTIVE_UNDECIDED,
|
||||
XmppAxolotlSession.Trust.UNDECIDED);
|
||||
setTrustOnSessions(jid, newDevices, XmppAxolotlSession.Trust.INACTIVE_UNTRUSTED,
|
||||
XmppAxolotlSession.Trust.UNTRUSTED);
|
||||
for (Integer deviceId : newDevices) {
|
||||
AxolotlAddress address = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId);
|
||||
XmppAxolotlSession session = sessions.get(address);
|
||||
if (session != null && session.getFingerprint() != null) {
|
||||
if (!session.getTrust().isActive()) {
|
||||
session.setTrust(session.getTrust().toActive());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.deviceIds.put(jid, deviceIds);
|
||||
mXmppConnectionService.keyStatusUpdated(null);
|
||||
}
|
||||
|
@ -428,7 +417,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
}
|
||||
|
||||
public void purgeKey(final String fingerprint) {
|
||||
axolotlStore.setFingerprintTrust(fingerprint.replaceAll("\\s", ""), XmppAxolotlSession.Trust.COMPROMISED);
|
||||
axolotlStore.setFingerprintTrust(fingerprint.replaceAll("\\s", ""), FingerprintStatus.createCompromised());
|
||||
}
|
||||
|
||||
public void publishOwnDeviceIdIfNeeded() {
|
||||
|
@ -692,16 +681,16 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
return jids;
|
||||
}
|
||||
|
||||
public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) {
|
||||
return axolotlStore.getFingerprintTrust(fingerprint);
|
||||
public FingerprintStatus getFingerprintTrust(String fingerprint) {
|
||||
return axolotlStore.getFingerprintStatus(fingerprint);
|
||||
}
|
||||
|
||||
public X509Certificate getFingerprintCertificate(String fingerprint) {
|
||||
return axolotlStore.getFingerprintCertificate(fingerprint);
|
||||
}
|
||||
|
||||
public void setFingerprintTrust(String fingerprint, XmppAxolotlSession.Trust trust) {
|
||||
axolotlStore.setFingerprintTrust(fingerprint, trust);
|
||||
public void setFingerprintTrust(String fingerprint, FingerprintStatus status) {
|
||||
axolotlStore.setFingerprintTrust(fingerprint, status);
|
||||
}
|
||||
|
||||
private void verifySessionWithPEP(final XmppAxolotlSession session) {
|
||||
|
@ -724,7 +713,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
mXmppConnectionService.getMemorizingTrustManager().getNonInteractive().checkClientTrusted(verification.first, "RSA");
|
||||
String fingerprint = session.getFingerprint();
|
||||
Log.d(Config.LOGTAG, "verified session with x.509 signature. fingerprint was: "+fingerprint);
|
||||
setFingerprintTrust(fingerprint, XmppAxolotlSession.Trust.TRUSTED_X509);
|
||||
setFingerprintTrust(fingerprint, FingerprintStatus.createActiveVerified(true));
|
||||
axolotlStore.setFingerprintCertificate(fingerprint, verification.first[0]);
|
||||
fetchStatusMap.put(address, FetchStatus.SUCCESS_VERIFIED);
|
||||
Bundle information = CryptoHelper.extractCertificateInformation(verification.first[0]);
|
||||
|
@ -921,8 +910,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
|||
sessions.addAll(findOwnSessions());
|
||||
boolean verified = false;
|
||||
for(XmppAxolotlSession session : sessions) {
|
||||
if (session.getTrust().trusted()) {
|
||||
if (session.getTrust() == XmppAxolotlSession.Trust.TRUSTED_X509) {
|
||||
if (session.getTrust().isTrustedAndActive()) {
|
||||
if (session.getTrust().getTrust() == FingerprintStatus.Trust.VERIFIED_X509) {
|
||||
verified = true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package eu.siacs.conversations.crypto.axolotl;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
|
||||
public class FingerprintStatus {
|
||||
|
||||
private Trust trust = Trust.UNTRUSTED;
|
||||
private boolean active = false;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FingerprintStatus that = (FingerprintStatus) o;
|
||||
|
||||
return active == that.active && trust == that.trust;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = trust.hashCode();
|
||||
result = 31 * result + (active ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private FingerprintStatus() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public ContentValues toContentValues() {
|
||||
final ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(SQLiteAxolotlStore.TRUST,trust.toString());
|
||||
contentValues.put(SQLiteAxolotlStore.ACTIVE,active ? 1 : 0);
|
||||
return contentValues;
|
||||
}
|
||||
|
||||
public static FingerprintStatus fromCursor(Cursor cursor) {
|
||||
final FingerprintStatus status = new FingerprintStatus();
|
||||
try {
|
||||
status.trust = Trust.valueOf(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.TRUST)));
|
||||
} catch(IllegalArgumentException e) {
|
||||
status.trust = Trust.UNTRUSTED;
|
||||
}
|
||||
status.active = cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.ACTIVE)) > 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
public static FingerprintStatus createActiveUndecided() {
|
||||
final FingerprintStatus status = new FingerprintStatus();
|
||||
status.trust = Trust.UNDECIDED;
|
||||
status.active = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
public static FingerprintStatus createActiveVerified(boolean x509) {
|
||||
final FingerprintStatus status = new FingerprintStatus();
|
||||
status.trust = x509 ? Trust.VERIFIED_X509 : Trust.VERIFIED;
|
||||
status.active = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
public static FingerprintStatus createActive(boolean trusted) {
|
||||
final FingerprintStatus status = new FingerprintStatus();
|
||||
status.trust = trusted ? Trust.TRUSTED : Trust.UNTRUSTED;
|
||||
status.active = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
public boolean isTrustedAndActive() {
|
||||
return active && isTrusted();
|
||||
}
|
||||
|
||||
public boolean isTrusted() {
|
||||
return trust == Trust.TRUSTED || trust == Trust.VERIFIED || trust == Trust.VERIFIED_X509;
|
||||
}
|
||||
|
||||
public boolean isCompromised() {
|
||||
return trust == Trust.COMPROMISED;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public FingerprintStatus toActive() {
|
||||
FingerprintStatus status = new FingerprintStatus();
|
||||
status.trust = trust;
|
||||
status.active = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
public FingerprintStatus toInactive() {
|
||||
FingerprintStatus status = new FingerprintStatus();
|
||||
status.trust = trust;
|
||||
status.active = false;
|
||||
return status;
|
||||
}
|
||||
|
||||
public Trust getTrust() {
|
||||
return trust;
|
||||
}
|
||||
|
||||
public static FingerprintStatus createCompromised() {
|
||||
FingerprintStatus status = new FingerprintStatus();
|
||||
status.active = false;
|
||||
status.trust = Trust.COMPROMISED;
|
||||
return status;
|
||||
}
|
||||
|
||||
public enum Trust {
|
||||
COMPROMISED,
|
||||
UNDECIDED,
|
||||
UNTRUSTED,
|
||||
TRUSTED,
|
||||
VERIFIED,
|
||||
VERIFIED_X509
|
||||
}
|
||||
|
||||
}
|
|
@ -35,7 +35,9 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||
public static final String KEY = "key";
|
||||
public static final String FINGERPRINT = "fingerprint";
|
||||
public static final String NAME = "name";
|
||||
public static final String TRUSTED = "trusted";
|
||||
public static final String TRUSTED = "trusted"; //no longer used
|
||||
public static final String TRUST = "trust";
|
||||
public static final String ACTIVE = "active";
|
||||
public static final String OWN = "ownkey";
|
||||
public static final String CERTIFICATE = "certificate";
|
||||
|
||||
|
@ -51,11 +53,11 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||
private int localRegistrationId;
|
||||
private int currentPreKeyId = 0;
|
||||
|
||||
private final LruCache<String, XmppAxolotlSession.Trust> trustCache =
|
||||
new LruCache<String, XmppAxolotlSession.Trust>(NUM_TRUSTS_TO_CACHE) {
|
||||
private final LruCache<String, FingerprintStatus> trustCache =
|
||||
new LruCache<String, FingerprintStatus>(NUM_TRUSTS_TO_CACHE) {
|
||||
@Override
|
||||
protected XmppAxolotlSession.Trust create(String fingerprint) {
|
||||
return mXmppConnectionService.databaseBackend.isIdentityKeyTrusted(account, fingerprint);
|
||||
protected FingerprintStatus create(String fingerprint) {
|
||||
return mXmppConnectionService.databaseBackend.getFingerprintStatus(account, fingerprint);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -208,12 +210,12 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||
return true;
|
||||
}
|
||||
|
||||
public XmppAxolotlSession.Trust getFingerprintTrust(String fingerprint) {
|
||||
public FingerprintStatus getFingerprintStatus(String fingerprint) {
|
||||
return (fingerprint == null)? null : trustCache.get(fingerprint);
|
||||
}
|
||||
|
||||
public void setFingerprintTrust(String fingerprint, XmppAxolotlSession.Trust trust) {
|
||||
mXmppConnectionService.databaseBackend.setIdentityKeyTrust(account, fingerprint, trust);
|
||||
public void setFingerprintTrust(String fingerprint, FingerprintStatus status) {
|
||||
mXmppConnectionService.databaseBackend.setIdentityKeyTrust(account, fingerprint, status);
|
||||
trustCache.remove(fingerprint);
|
||||
}
|
||||
|
||||
|
@ -225,8 +227,8 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
|||
return mXmppConnectionService.databaseBackend.getIdentityKeyCertifcate(account, fingerprint);
|
||||
}
|
||||
|
||||
public Set<IdentityKey> getContactKeysWithTrust(String bareJid, XmppAxolotlSession.Trust trust) {
|
||||
return mXmppConnectionService.databaseBackend.loadIdentityKeys(account, bareJid, trust);
|
||||
public Set<IdentityKey> getContactKeysWithTrust(String bareJid, FingerprintStatus status) {
|
||||
return mXmppConnectionService.databaseBackend.loadIdentityKeys(account, bareJid, status);
|
||||
}
|
||||
|
||||
public long getContactNumTrustedKeys(String bareJid) {
|
||||
|
|
|
@ -19,9 +19,6 @@ import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
|
|||
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
||||
import org.whispersystems.libaxolotl.protocol.WhisperMessage;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
|
||||
|
@ -34,76 +31,6 @@ public class XmppAxolotlSession {
|
|||
private Integer preKeyId = null;
|
||||
private boolean fresh = true;
|
||||
|
||||
public enum Trust {
|
||||
UNDECIDED(0),
|
||||
TRUSTED(1),
|
||||
UNTRUSTED(2),
|
||||
COMPROMISED(3),
|
||||
INACTIVE_TRUSTED(4),
|
||||
INACTIVE_UNDECIDED(5),
|
||||
INACTIVE_UNTRUSTED(6),
|
||||
TRUSTED_X509(7),
|
||||
INACTIVE_TRUSTED_X509(8);
|
||||
|
||||
private static final Map<Integer, Trust> trustsByValue = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Trust trust : Trust.values()) {
|
||||
trustsByValue.put(trust.getCode(), trust);
|
||||
}
|
||||
}
|
||||
|
||||
private final int code;
|
||||
|
||||
Trust(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case UNDECIDED:
|
||||
return "Trust undecided " + getCode();
|
||||
case TRUSTED:
|
||||
return "Trusted " + getCode();
|
||||
case COMPROMISED:
|
||||
return "Compromised " + getCode();
|
||||
case INACTIVE_TRUSTED:
|
||||
return "Inactive (Trusted)" + getCode();
|
||||
case INACTIVE_UNDECIDED:
|
||||
return "Inactive (Undecided)" + getCode();
|
||||
case INACTIVE_UNTRUSTED:
|
||||
return "Inactive (Untrusted)" + getCode();
|
||||
case TRUSTED_X509:
|
||||
return "Trusted (X509) " + getCode();
|
||||
case INACTIVE_TRUSTED_X509:
|
||||
return "Inactive (Trusted (X509)) " + getCode();
|
||||
case UNTRUSTED:
|
||||
default:
|
||||
return "Untrusted " + getCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static Trust fromBoolean(Boolean trusted) {
|
||||
return trusted ? TRUSTED : UNTRUSTED;
|
||||
}
|
||||
|
||||
public static Trust fromCode(int code) {
|
||||
return trustsByValue.get(code);
|
||||
}
|
||||
|
||||
public boolean trusted() {
|
||||
return this == TRUSTED_X509 || this == TRUSTED;
|
||||
}
|
||||
|
||||
public boolean trustedInactive() {
|
||||
return this == INACTIVE_TRUSTED_X509 || this == INACTIVE_TRUSTED;
|
||||
}
|
||||
}
|
||||
|
||||
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, IdentityKey identityKey) {
|
||||
this(account, store, remoteAddress);
|
||||
this.identityKey = identityKey;
|
||||
|
@ -145,75 +72,60 @@ public class XmppAxolotlSession {
|
|||
this.fresh = false;
|
||||
}
|
||||
|
||||
protected void setTrust(Trust trust) {
|
||||
sqLiteAxolotlStore.setFingerprintTrust(getFingerprint(), trust);
|
||||
protected void setTrust(FingerprintStatus status) {
|
||||
sqLiteAxolotlStore.setFingerprintTrust(getFingerprint(), status);
|
||||
}
|
||||
|
||||
protected Trust getTrust() {
|
||||
Trust trust = sqLiteAxolotlStore.getFingerprintTrust(getFingerprint());
|
||||
return (trust == null) ? Trust.UNDECIDED : trust;
|
||||
protected FingerprintStatus getTrust() {
|
||||
FingerprintStatus status = sqLiteAxolotlStore.getFingerprintStatus(getFingerprint());
|
||||
return (status == null) ? FingerprintStatus.createActiveUndecided() : status;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] processReceiving(byte[] encryptedKey) {
|
||||
byte[] plaintext = null;
|
||||
Trust trust = getTrust();
|
||||
switch (trust) {
|
||||
case INACTIVE_TRUSTED:
|
||||
case UNDECIDED:
|
||||
case UNTRUSTED:
|
||||
case TRUSTED:
|
||||
case INACTIVE_TRUSTED_X509:
|
||||
case TRUSTED_X509:
|
||||
FingerprintStatus status = getTrust();
|
||||
if (!status.isCompromised()) {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
|
||||
if (!message.getPreKeyId().isPresent()) {
|
||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage did not contain a PreKeyId");
|
||||
break;
|
||||
}
|
||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
||||
IdentityKey msgIdentityKey = message.getIdentityKey();
|
||||
if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) {
|
||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Had session with fingerprint " + this.getFingerprint() + ", received message with fingerprint " + msgIdentityKey.getFingerprint());
|
||||
} else {
|
||||
this.identityKey = msgIdentityKey;
|
||||
plaintext = cipher.decrypt(message);
|
||||
preKeyId = message.getPreKeyId().get();
|
||||
}
|
||||
} catch (InvalidMessageException | InvalidVersionException e) {
|
||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received");
|
||||
WhisperMessage message = new WhisperMessage(encryptedKey);
|
||||
plaintext = cipher.decrypt(message);
|
||||
} catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
|
||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
||||
PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
|
||||
if (!message.getPreKeyId().isPresent()) {
|
||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage did not contain a PreKeyId");
|
||||
return null;
|
||||
}
|
||||
} catch (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
|
||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
|
||||
IdentityKey msgIdentityKey = message.getIdentityKey();
|
||||
if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) {
|
||||
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Had session with fingerprint " + this.getFingerprint() + ", received message with fingerprint " + msgIdentityKey.getFingerprint());
|
||||
} else {
|
||||
this.identityKey = msgIdentityKey;
|
||||
plaintext = cipher.decrypt(message);
|
||||
preKeyId = message.getPreKeyId().get();
|
||||
}
|
||||
} catch (InvalidMessageException | InvalidVersionException e) {
|
||||
Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received");
|
||||
WhisperMessage message = new WhisperMessage(encryptedKey);
|
||||
plaintext = cipher.decrypt(message);
|
||||
} catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
|
||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
||||
}
|
||||
} catch (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
|
||||
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
if (plaintext != null) {
|
||||
if (trust == Trust.INACTIVE_TRUSTED) {
|
||||
setTrust(Trust.TRUSTED);
|
||||
} else if (trust == Trust.INACTIVE_TRUSTED_X509) {
|
||||
setTrust(Trust.TRUSTED_X509);
|
||||
}
|
||||
if (plaintext != null) {
|
||||
if (!status.isActive()) {
|
||||
setTrust(status.toActive());
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case COMPROMISED:
|
||||
default:
|
||||
// ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] processSending(@NonNull byte[] outgoingMessage) {
|
||||
Trust trust = getTrust();
|
||||
if (trust.trusted()) {
|
||||
FingerprintStatus status = getTrust();
|
||||
if (status.isTrustedAndActive()) {
|
||||
CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
|
||||
return ciphertextMessage.serialize();
|
||||
} else {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.GeoHelper;
|
||||
|
@ -811,8 +812,8 @@ public class Message extends AbstractEntity {
|
|||
}
|
||||
|
||||
public boolean isTrusted() {
|
||||
XmppAxolotlSession.Trust t = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint);
|
||||
return t != null && t.trusted();
|
||||
FingerprintStatus s = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint);
|
||||
return s != null && s.isTrustedAndActive();
|
||||
}
|
||||
|
||||
private int getPreviousEncryption() {
|
||||
|
|
|
@ -27,17 +27,19 @@ import java.security.cert.CertificateException;
|
|||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.json.JSONException;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
|
@ -45,7 +47,6 @@ import eu.siacs.conversations.entities.Message;
|
|||
import eu.siacs.conversations.entities.PresenceTemplate;
|
||||
import eu.siacs.conversations.entities.Roster;
|
||||
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
||||
import eu.siacs.conversations.generator.AbstractGenerator;
|
||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||
|
||||
|
@ -54,7 +55,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
private static DatabaseBackend instance = null;
|
||||
|
||||
private static final String DATABASE_NAME = "history";
|
||||
private static final int DATABASE_VERSION = 30;
|
||||
private static final int DATABASE_VERSION = 31;
|
||||
|
||||
private static String CREATE_CONTATCS_STATEMENT = "create table "
|
||||
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
|
||||
|
@ -129,7 +130,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
+ SQLiteAxolotlStore.OWN + " INTEGER, "
|
||||
+ SQLiteAxolotlStore.FINGERPRINT + " TEXT, "
|
||||
+ SQLiteAxolotlStore.CERTIFICATE + " BLOB, "
|
||||
+ SQLiteAxolotlStore.TRUSTED + " INTEGER, "
|
||||
+ SQLiteAxolotlStore.TRUST + " TEXT, "
|
||||
+ SQLiteAxolotlStore.ACTIVE + " NUMBER, "
|
||||
+ SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
|
||||
+ SQLiteAxolotlStore.ACCOUNT
|
||||
+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, "
|
||||
|
@ -297,7 +299,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
deleteSession(db, account, ownAddress);
|
||||
IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account);
|
||||
if (identityKeyPair != null) {
|
||||
setIdentityKeyTrust(db, account, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), XmppAxolotlSession.Trust.TRUSTED);
|
||||
String[] selectionArgs = {
|
||||
account.getUuid(),
|
||||
identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", "")
|
||||
};
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SQLiteAxolotlStore.TRUSTED, 2);
|
||||
db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, values,
|
||||
SQLiteAxolotlStore.ACCOUNT + " = ? AND "
|
||||
+ SQLiteAxolotlStore.FINGERPRINT + " = ? ",
|
||||
selectionArgs);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not load own identity key pair");
|
||||
}
|
||||
|
@ -346,6 +357,33 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
if (oldVersion < 30 && newVersion >= 30) {
|
||||
db.execSQL(CREATE_START_TIMES_TABLE);
|
||||
}
|
||||
if (oldVersion < 31 && newVersion >= 31) {
|
||||
db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.TRUST + " TEXT");
|
||||
db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.ACTIVE + " NUMBER");
|
||||
HashMap<Integer,ContentValues> migration = new HashMap<>();
|
||||
migration.put(0,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNDECIDED,true));
|
||||
migration.put(1,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED, true));
|
||||
migration.put(2,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNTRUSTED, true));
|
||||
migration.put(3,createFingerprintStatusContentValues(FingerprintStatus.Trust.COMPROMISED, false));
|
||||
migration.put(4,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED, false));
|
||||
migration.put(5,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNDECIDED, false));
|
||||
migration.put(6,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNTRUSTED, false));
|
||||
migration.put(7,createFingerprintStatusContentValues(FingerprintStatus.Trust.VERIFIED_X509, true));
|
||||
migration.put(8,createFingerprintStatusContentValues(FingerprintStatus.Trust.VERIFIED_X509, false));
|
||||
for(Map.Entry<Integer,ContentValues> entry : migration.entrySet()) {
|
||||
String whereClause = SQLiteAxolotlStore.TRUSTED+"=?";
|
||||
String[] where = {String.valueOf(entry.getKey())};
|
||||
db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME,entry.getValue(),whereClause,where);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static ContentValues createFingerprintStatusContentValues(FingerprintStatus.Trust trust, boolean active) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SQLiteAxolotlStore.TRUST,trust.toString());
|
||||
values.put(SQLiteAxolotlStore.ACTIVE,active ? 1 : 0);
|
||||
return values;
|
||||
}
|
||||
|
||||
private void canonicalizeJids(SQLiteDatabase db) {
|
||||
|
@ -1006,7 +1044,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, Boolean own, String fingerprint) {
|
||||
String[] columns = {SQLiteAxolotlStore.TRUSTED,
|
||||
String[] columns = {SQLiteAxolotlStore.TRUST,
|
||||
SQLiteAxolotlStore.ACTIVE,
|
||||
SQLiteAxolotlStore.KEY};
|
||||
ArrayList<String> selectionArgs = new ArrayList<>(4);
|
||||
selectionArgs.add(account.getUuid());
|
||||
|
@ -1058,14 +1097,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
return loadIdentityKeys(account, name, null);
|
||||
}
|
||||
|
||||
public Set<IdentityKey> loadIdentityKeys(Account account, String name, XmppAxolotlSession.Trust trust) {
|
||||
public Set<IdentityKey> loadIdentityKeys(Account account, String name, FingerprintStatus status) {
|
||||
Set<IdentityKey> identityKeys = new HashSet<>();
|
||||
Cursor cursor = getIdentityKeyCursor(account, name, false);
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
if (trust != null &&
|
||||
cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.TRUSTED))
|
||||
!= trust.getCode()) {
|
||||
if (status != null && !FingerprintStatus.fromCursor(cursor).equals(status)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
@ -1084,22 +1121,24 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
String[] args = {
|
||||
account.getUuid(),
|
||||
name,
|
||||
String.valueOf(XmppAxolotlSession.Trust.TRUSTED.getCode()),
|
||||
String.valueOf(XmppAxolotlSession.Trust.TRUSTED_X509.getCode())
|
||||
FingerprintStatus.Trust.TRUSTED.toString(),
|
||||
FingerprintStatus.Trust.VERIFIED.toString(),
|
||||
FingerprintStatus.Trust.VERIFIED_X509.toString()
|
||||
};
|
||||
return DatabaseUtils.queryNumEntries(db, SQLiteAxolotlStore.IDENTITIES_TABLENAME,
|
||||
SQLiteAxolotlStore.ACCOUNT + " = ?"
|
||||
+ " AND " + SQLiteAxolotlStore.NAME + " = ?"
|
||||
+ " AND (" + SQLiteAxolotlStore.TRUSTED + " = ? OR " + SQLiteAxolotlStore.TRUSTED + " = ?)",
|
||||
+ " AND (" + SQLiteAxolotlStore.TRUST + " = ? OR " + SQLiteAxolotlStore.TRUST + " = ? OR " +SQLiteAxolotlStore.TRUST +" = ?)"
|
||||
+ " AND " +SQLiteAxolotlStore.ACTIVE + " > 0",
|
||||
args
|
||||
);
|
||||
}
|
||||
|
||||
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized) {
|
||||
storeIdentityKey(account, name, own, fingerprint, base64Serialized, XmppAxolotlSession.Trust.UNDECIDED);
|
||||
storeIdentityKey(account, name, own, fingerprint, base64Serialized, FingerprintStatus.createActiveUndecided());
|
||||
}
|
||||
|
||||
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized, XmppAxolotlSession.Trust trusted) {
|
||||
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized, FingerprintStatus status) {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid());
|
||||
|
@ -1107,35 +1146,34 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
values.put(SQLiteAxolotlStore.OWN, own ? 1 : 0);
|
||||
values.put(SQLiteAxolotlStore.FINGERPRINT, fingerprint);
|
||||
values.put(SQLiteAxolotlStore.KEY, base64Serialized);
|
||||
values.put(SQLiteAxolotlStore.TRUSTED, trusted.getCode());
|
||||
values.putAll(status.toContentValues());
|
||||
db.insert(SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
||||
}
|
||||
|
||||
public XmppAxolotlSession.Trust isIdentityKeyTrusted(Account account, String fingerprint) {
|
||||
public FingerprintStatus getFingerprintStatus(Account account, String fingerprint) {
|
||||
Cursor cursor = getIdentityKeyCursor(account, fingerprint);
|
||||
XmppAxolotlSession.Trust trust = null;
|
||||
final FingerprintStatus status;
|
||||
if (cursor.getCount() > 0) {
|
||||
cursor.moveToFirst();
|
||||
int trustValue = cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.TRUSTED));
|
||||
trust = XmppAxolotlSession.Trust.fromCode(trustValue);
|
||||
status = FingerprintStatus.fromCursor(cursor);
|
||||
} else {
|
||||
status = null;
|
||||
}
|
||||
cursor.close();
|
||||
return trust;
|
||||
return status;
|
||||
}
|
||||
|
||||
public boolean setIdentityKeyTrust(Account account, String fingerprint, XmppAxolotlSession.Trust trust) {
|
||||
public boolean setIdentityKeyTrust(Account account, String fingerprint, FingerprintStatus fingerprintStatus) {
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
return setIdentityKeyTrust(db, account, fingerprint, trust);
|
||||
return setIdentityKeyTrust(db, account, fingerprint, fingerprintStatus);
|
||||
}
|
||||
|
||||
private boolean setIdentityKeyTrust(SQLiteDatabase db, Account account, String fingerprint, XmppAxolotlSession.Trust trust) {
|
||||
private boolean setIdentityKeyTrust(SQLiteDatabase db, Account account, String fingerprint, FingerprintStatus status) {
|
||||
String[] selectionArgs = {
|
||||
account.getUuid(),
|
||||
fingerprint
|
||||
};
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SQLiteAxolotlStore.TRUSTED, trust.getCode());
|
||||
int rows = db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, values,
|
||||
int rows = db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, status.toContentValues(),
|
||||
SQLiteAxolotlStore.ACCOUNT + " = ? AND "
|
||||
+ SQLiteAxolotlStore.FINGERPRINT + " = ? ",
|
||||
selectionArgs);
|
||||
|
@ -1194,7 +1232,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) {
|
||||
storeIdentityKey(account, account.getJid().toBareJid().toPreppedString(), true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), XmppAxolotlSession.Trust.TRUSTED);
|
||||
storeIdentityKey(account, account.getJid().toBareJid().toPreppedString(), true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), FingerprintStatus.createActiveVerified(false));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import eu.siacs.conversations.Config;
|
|||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
|
@ -509,8 +510,8 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
|||
}
|
||||
|
||||
private void onOmemoKeyClicked(Account account, String fingerprint) {
|
||||
final XmppAxolotlSession.Trust trust = account.getAxolotlService().getFingerprintTrust(fingerprint);
|
||||
if (Config.X509_VERIFICATION && trust != null && trust == XmppAxolotlSession.Trust.TRUSTED_X509) {
|
||||
FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint);
|
||||
if (Config.X509_VERIFICATION && status != null && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509) {
|
||||
X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint);
|
||||
if (x509Certificate != null) {
|
||||
showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate));
|
||||
|
|
|
@ -49,6 +49,7 @@ import de.timroes.android.listview.EnhancedListView;
|
|||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Blockable;
|
||||
|
@ -1677,8 +1678,8 @@ public class ConversationActivity extends XmppActivity
|
|||
AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService();
|
||||
final List<Jid> targets = axolotlService.getCryptoTargets(mSelectedConversation);
|
||||
boolean hasUnaccepted = !mSelectedConversation.getAcceptedCryptoTargets().containsAll(targets);
|
||||
boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty();
|
||||
boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty();
|
||||
boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(FingerprintStatus.createActiveUndecided()).isEmpty();
|
||||
boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), targets).isEmpty();
|
||||
boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty();
|
||||
boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets);
|
||||
if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys || hasUnaccepted) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Set;
|
|||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
|
@ -108,7 +109,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
for(final String fingerprint : ownKeysToTrust.keySet()) {
|
||||
hasOwnKeys = true;
|
||||
addFingerprintRowWithListeners(ownKeys, mAccount, fingerprint, false,
|
||||
XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)), false,
|
||||
FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false,
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
|
@ -133,7 +134,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
final Map<String, Boolean> fingerprints = entry.getValue();
|
||||
for (final String fingerprint : fingerprints.keySet()) {
|
||||
addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false,
|
||||
XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false,
|
||||
FingerprintStatus.createActive(fingerprints.get(fingerprint)), false,
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
|
@ -184,7 +185,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets();
|
||||
ownKeysToTrust.clear();
|
||||
AxolotlService service = this.mAccount.getAxolotlService();
|
||||
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED);
|
||||
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
|
||||
for(final IdentityKey identityKey : ownKeysSet) {
|
||||
if(!ownKeysToTrust.containsKey(identityKey)) {
|
||||
ownKeysToTrust.put(identityKey.getFingerprint().replaceAll("\\s", ""), false);
|
||||
|
@ -193,9 +194,9 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
synchronized (this.foreignKeysToTrust) {
|
||||
foreignKeysToTrust.clear();
|
||||
for (Jid jid : contactJids) {
|
||||
Set<IdentityKey> foreignKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, jid);
|
||||
Set<IdentityKey> foreignKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), jid);
|
||||
if (hasNoOtherTrustedKeys(jid) && ownKeysSet.size() == 0) {
|
||||
foreignKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, jid));
|
||||
foreignKeysSet.addAll(service.getKeysWithTrust(FingerprintStatus.createActive(false), jid));
|
||||
}
|
||||
Map<String, Boolean> foreignFingerprints = new HashMap<>();
|
||||
for (final IdentityKey identityKey : foreignKeysSet) {
|
||||
|
@ -280,7 +281,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
for(final String fingerprint :ownKeysToTrust.keySet()) {
|
||||
mAccount.getAxolotlService().setFingerprintTrust(
|
||||
fingerprint,
|
||||
XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)));
|
||||
FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
|
||||
}
|
||||
List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets();
|
||||
synchronized (this.foreignKeysToTrust) {
|
||||
|
@ -293,7 +294,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
|||
for (final String fingerprint : value.keySet()) {
|
||||
mAccount.getAxolotlService().setFingerprintTrust(
|
||||
fingerprint,
|
||||
XmppAxolotlSession.Trust.fromBoolean(value.get(fingerprint)));
|
||||
FingerprintStatus.createActive(value.get(fingerprint)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Contact;
|
||||
|
@ -780,25 +781,21 @@ public abstract class XmppActivity extends Activity {
|
|||
}
|
||||
|
||||
protected boolean addFingerprintRow(LinearLayout keys, final Account account, final String fingerprint, boolean highlight, View.OnClickListener onKeyClickedListener) {
|
||||
final XmppAxolotlSession.Trust trust = account.getAxolotlService()
|
||||
.getFingerprintTrust(fingerprint);
|
||||
if (trust == null) {
|
||||
final FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint);
|
||||
if (status == null) {
|
||||
return false;
|
||||
}
|
||||
return addFingerprintRowWithListeners(keys, account, fingerprint, highlight, trust, true,
|
||||
return addFingerprintRowWithListeners(keys, account, fingerprint, highlight, status, true,
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
account.getAxolotlService().setFingerprintTrust(fingerprint,
|
||||
(isChecked) ? XmppAxolotlSession.Trust.TRUSTED :
|
||||
XmppAxolotlSession.Trust.UNTRUSTED);
|
||||
account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(isChecked));
|
||||
}
|
||||
},
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
account.getAxolotlService().setFingerprintTrust(fingerprint,
|
||||
XmppAxolotlSession.Trust.UNTRUSTED);
|
||||
account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(true));
|
||||
v.setEnabled(true);
|
||||
}
|
||||
},
|
||||
|
@ -810,13 +807,13 @@ public abstract class XmppActivity extends Activity {
|
|||
protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account,
|
||||
final String fingerprint,
|
||||
boolean highlight,
|
||||
XmppAxolotlSession.Trust trust,
|
||||
FingerprintStatus status,
|
||||
boolean showTag,
|
||||
CompoundButton.OnCheckedChangeListener
|
||||
onCheckedChangeListener,
|
||||
View.OnClickListener onClickListener,
|
||||
View.OnClickListener onKeyClickedListener) {
|
||||
if (trust == XmppAxolotlSession.Trust.COMPROMISED) {
|
||||
if (status.isCompromised()) {
|
||||
return false;
|
||||
}
|
||||
View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false);
|
||||
|
@ -826,8 +823,6 @@ public abstract class XmppActivity extends Activity {
|
|||
keyType.setOnClickListener(onKeyClickedListener);
|
||||
Switch trustToggle = (Switch) view.findViewById(R.id.tgl_trust);
|
||||
trustToggle.setVisibility(View.VISIBLE);
|
||||
trustToggle.setOnCheckedChangeListener(onCheckedChangeListener);
|
||||
trustToggle.setOnClickListener(onClickListener);
|
||||
final View.OnLongClickListener purge = new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
|
@ -835,50 +830,46 @@ public abstract class XmppActivity extends Activity {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
boolean active = true;
|
||||
view.setOnLongClickListener(purge);
|
||||
key.setOnLongClickListener(purge);
|
||||
keyType.setOnLongClickListener(purge);
|
||||
boolean x509 = Config.X509_VERIFICATION
|
||||
&& (trust == XmppAxolotlSession.Trust.TRUSTED_X509 || trust == XmppAxolotlSession.Trust.INACTIVE_TRUSTED_X509);
|
||||
switch (trust) {
|
||||
case UNTRUSTED:
|
||||
case TRUSTED:
|
||||
case TRUSTED_X509:
|
||||
trustToggle.setChecked(trust.trusted(), false);
|
||||
trustToggle.setEnabled(!Config.X509_VERIFICATION || trust != XmppAxolotlSession.Trust.TRUSTED_X509);
|
||||
if (Config.X509_VERIFICATION && trust == XmppAxolotlSession.Trust.TRUSTED_X509) {
|
||||
trustToggle.setOnClickListener(null);
|
||||
boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509;
|
||||
final View.OnClickListener toast;
|
||||
if (status.isActive()) {
|
||||
key.setTextColor(getPrimaryTextColor());
|
||||
keyType.setTextColor(getSecondaryTextColor());
|
||||
trustToggle.setOnCheckedChangeListener(onCheckedChangeListener);
|
||||
if (status.getTrust() == FingerprintStatus.Trust.UNDECIDED) {
|
||||
trustToggle.setOnClickListener(onClickListener);
|
||||
trustToggle.setEnabled(false);
|
||||
} else {
|
||||
trustToggle.setOnClickListener(null);
|
||||
trustToggle.setChecked(status.isTrusted(), false);
|
||||
trustToggle.setEnabled(true);
|
||||
}
|
||||
toast = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hideToast();
|
||||
}
|
||||
key.setTextColor(getPrimaryTextColor());
|
||||
keyType.setTextColor(getSecondaryTextColor());
|
||||
break;
|
||||
case UNDECIDED:
|
||||
trustToggle.setChecked(false, false);
|
||||
trustToggle.setEnabled(false);
|
||||
key.setTextColor(getPrimaryTextColor());
|
||||
keyType.setTextColor(getSecondaryTextColor());
|
||||
break;
|
||||
case INACTIVE_UNTRUSTED:
|
||||
case INACTIVE_UNDECIDED:
|
||||
trustToggle.setOnClickListener(null);
|
||||
trustToggle.setChecked(false, false);
|
||||
trustToggle.setEnabled(false);
|
||||
key.setTextColor(getTertiaryTextColor());
|
||||
keyType.setTextColor(getTertiaryTextColor());
|
||||
active = false;
|
||||
break;
|
||||
case INACTIVE_TRUSTED:
|
||||
case INACTIVE_TRUSTED_X509:
|
||||
trustToggle.setOnClickListener(null);
|
||||
trustToggle.setChecked(true, false);
|
||||
trustToggle.setEnabled(false);
|
||||
key.setTextColor(getTertiaryTextColor());
|
||||
keyType.setTextColor(getTertiaryTextColor());
|
||||
active = false;
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
key.setTextColor(getTertiaryTextColor());
|
||||
keyType.setTextColor(getTertiaryTextColor());
|
||||
trustToggle.setOnClickListener(null);
|
||||
trustToggle.setEnabled(false);
|
||||
trustToggle.setChecked(status.isTrusted(), false);
|
||||
toast = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
replaceToast(getString(R.string.this_device_is_no_longer_in_use), false);
|
||||
}
|
||||
};
|
||||
trustToggle.setOnClickListener(toast);
|
||||
}
|
||||
|
||||
view.setOnClickListener(toast);
|
||||
key.setOnClickListener(toast);
|
||||
keyType.setOnClickListener(toast);
|
||||
if (showTag) {
|
||||
keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint));
|
||||
} else {
|
||||
|
@ -893,27 +884,6 @@ public abstract class XmppActivity extends Activity {
|
|||
|
||||
key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2)));
|
||||
|
||||
final View.OnClickListener toast;
|
||||
if (!active) {
|
||||
toast = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
replaceToast(getString(R.string.this_device_is_no_longer_in_use), false);
|
||||
}
|
||||
};
|
||||
trustToggle.setOnClickListener(toast);
|
||||
} else {
|
||||
toast = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hideToast();
|
||||
}
|
||||
};
|
||||
}
|
||||
view.setOnClickListener(toast);
|
||||
key.setOnClickListener(toast);
|
||||
keyType.setOnClickListener(toast);
|
||||
|
||||
keys.addView(view);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Conversation;
|
||||
|
@ -203,11 +204,11 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
|||
viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_lock_white_18dp : R.drawable.ic_lock_black_18dp);
|
||||
viewHolder.indicator.setVisibility(View.VISIBLE);
|
||||
if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
|
||||
XmppAxolotlSession.Trust trust = message.getConversation()
|
||||
FingerprintStatus status = message.getConversation()
|
||||
.getAccount().getAxolotlService().getFingerprintTrust(
|
||||
message.getFingerprint());
|
||||
|
||||
if(trust == null || (!trust.trusted() && !trust.trustedInactive())) {
|
||||
if(status == null || (!status.isTrustedAndActive())) {
|
||||
viewHolder.indicator.setColorFilter(activity.getWarningTextColor());
|
||||
viewHolder.indicator.setAlpha(1.0f);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue