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