parse omemo fingerprints from uris
This commit is contained in:
parent
3f3b360eee
commit
7e2e42cb11
|
@ -98,6 +98,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preVerifyFingerprint(Contact contact, String fingerprint) {
|
||||||
|
axolotlStore.preVerifyFingerprint(contact.getAccount(), contact.getJid().toBareJid().toPreppedString(), fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
private static class AxolotlAddressMap<T> {
|
private static class AxolotlAddressMap<T> {
|
||||||
protected Map<String, Map<Integer, T>> map;
|
protected Map<String, Map<Integer, T>> map;
|
||||||
protected final Object MAP_LOCK = new Object();
|
protected final Object MAP_LOCK = new Object();
|
||||||
|
@ -200,7 +204,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
public void put(AxolotlAddress address, XmppAxolotlSession value) {
|
public void put(AxolotlAddress address, XmppAxolotlSession value) {
|
||||||
super.put(address, value);
|
super.put(address, value);
|
||||||
value.setNotFresh();
|
value.setNotFresh();
|
||||||
xmppConnectionService.syncRosterToDisk(account);
|
xmppConnectionService.syncRosterToDisk(account); //TODO why?
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(XmppAxolotlSession session) {
|
public void put(XmppAxolotlSession session) {
|
||||||
|
@ -417,7 +421,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void purgeKey(final String fingerprint) {
|
public void purgeKey(final String fingerprint) {
|
||||||
axolotlStore.setFingerprintTrust(fingerprint.replaceAll("\\s", ""), FingerprintStatus.createCompromised());
|
axolotlStore.setFingerprintStatus(fingerprint.replaceAll("\\s", ""), FingerprintStatus.createCompromised());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void publishOwnDeviceIdIfNeeded() {
|
public void publishOwnDeviceIdIfNeeded() {
|
||||||
|
@ -690,7 +694,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFingerprintTrust(String fingerprint, FingerprintStatus status) {
|
public void setFingerprintTrust(String fingerprint, FingerprintStatus status) {
|
||||||
axolotlStore.setFingerprintTrust(fingerprint, status);
|
axolotlStore.setFingerprintStatus(fingerprint, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifySessionWithPEP(final XmppAxolotlSession session) {
|
private void verifySessionWithPEP(final XmppAxolotlSession session) {
|
||||||
|
@ -749,14 +753,15 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
private void finishBuildingSessionsFromPEP(final AxolotlAddress address) {
|
private void finishBuildingSessionsFromPEP(final AxolotlAddress address) {
|
||||||
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toPreppedString(), 0);
|
||||||
if (!fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.PENDING)
|
Map<Integer, FetchStatus> own = fetchStatusMap.getAll(ownAddress);
|
||||||
&& !fetchStatusMap.getAll(address).containsValue(FetchStatus.PENDING)) {
|
Map<Integer, FetchStatus> remote = fetchStatusMap.getAll(address);
|
||||||
|
if (!own.containsValue(FetchStatus.PENDING) && !remote.containsValue(FetchStatus.PENDING)) {
|
||||||
FetchStatus report = null;
|
FetchStatus report = null;
|
||||||
if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.SUCCESS_VERIFIED)
|
if (own.containsValue(FetchStatus.SUCCESS) || remote.containsValue(FetchStatus.SUCCESS)) {
|
||||||
| fetchStatusMap.getAll(address).containsValue(FetchStatus.SUCCESS_VERIFIED)) {
|
report = FetchStatus.SUCCESS;
|
||||||
|
} else if (own.containsValue(FetchStatus.SUCCESS_VERIFIED) || remote.containsValue(FetchStatus.SUCCESS_VERIFIED)) {
|
||||||
report = FetchStatus.SUCCESS_VERIFIED;
|
report = FetchStatus.SUCCESS_VERIFIED;
|
||||||
} else if (fetchStatusMap.getAll(ownAddress).containsValue(FetchStatus.ERROR)
|
} else if (own.containsValue(FetchStatus.ERROR) || remote.containsValue(FetchStatus.ERROR)) {
|
||||||
|| fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) {
|
|
||||||
report = FetchStatus.ERROR;
|
report = FetchStatus.ERROR;
|
||||||
}
|
}
|
||||||
mXmppConnectionService.keyStatusUpdated(report);
|
mXmppConnectionService.keyStatusUpdated(report);
|
||||||
|
@ -812,7 +817,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
if (Config.X509_VERIFICATION) {
|
if (Config.X509_VERIFICATION) {
|
||||||
verifySessionWithPEP(session);
|
verifySessionWithPEP(session);
|
||||||
} else {
|
} else {
|
||||||
fetchStatusMap.put(address, FetchStatus.SUCCESS);
|
FingerprintStatus status = getFingerprintTrust(bundle.getIdentityKey().getFingerprint().replaceAll("\\s",""));
|
||||||
|
boolean verified = status != null && status.isVerified();
|
||||||
|
fetchStatusMap.put(address, verified ? FetchStatus.SUCCESS_VERIFIED : FetchStatus.SUCCESS);
|
||||||
finishBuildingSessionsFromPEP(address);
|
finishBuildingSessionsFromPEP(address);
|
||||||
}
|
}
|
||||||
} catch (UntrustedIdentityException | InvalidKeyException e) {
|
} catch (UntrustedIdentityException | InvalidKeyException e) {
|
||||||
|
|
|
@ -114,6 +114,20 @@ public class FingerprintStatus {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FingerprintStatus toVerified() {
|
||||||
|
FingerprintStatus status = new FingerprintStatus();
|
||||||
|
status.active = active;
|
||||||
|
status.trust = Trust.VERIFIED;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FingerprintStatus createInactiveVerified() {
|
||||||
|
final FingerprintStatus status = new FingerprintStatus();
|
||||||
|
status.trust = Trust.VERIFIED;
|
||||||
|
status.active = false;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Trust {
|
public enum Trust {
|
||||||
COMPROMISED,
|
COMPROMISED,
|
||||||
UNDECIDED,
|
UNDECIDED,
|
||||||
|
|
|
@ -187,7 +187,15 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
@Override
|
@Override
|
||||||
public void saveIdentity(String name, IdentityKey identityKey) {
|
public void saveIdentity(String name, IdentityKey identityKey) {
|
||||||
if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) {
|
if (!mXmppConnectionService.databaseBackend.loadIdentityKeys(account, name).contains(identityKey)) {
|
||||||
mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey);
|
String fingerprint = identityKey.getFingerprint().replaceAll("\\s", "");
|
||||||
|
FingerprintStatus status = getFingerprintStatus(fingerprint);
|
||||||
|
if (status == null) {
|
||||||
|
status = FingerprintStatus.createActiveUndecided(); //default for new keys
|
||||||
|
} else {
|
||||||
|
status = status.toActive();
|
||||||
|
}
|
||||||
|
mXmppConnectionService.databaseBackend.storeIdentityKey(account, name, identityKey, status);
|
||||||
|
trustCache.remove(fingerprint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +222,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
return (fingerprint == null)? null : trustCache.get(fingerprint);
|
return (fingerprint == null)? null : trustCache.get(fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFingerprintTrust(String fingerprint, FingerprintStatus status) {
|
public void setFingerprintStatus(String fingerprint, FingerprintStatus status) {
|
||||||
mXmppConnectionService.databaseBackend.setIdentityKeyTrust(account, fingerprint, status);
|
mXmppConnectionService.databaseBackend.setIdentityKeyTrust(account, fingerprint, status);
|
||||||
trustCache.remove(fingerprint);
|
trustCache.remove(fingerprint);
|
||||||
}
|
}
|
||||||
|
@ -430,4 +438,8 @@ public class SQLiteAxolotlStore implements AxolotlStore {
|
||||||
public void removeSignedPreKey(int signedPreKeyId) {
|
public void removeSignedPreKey(int signedPreKeyId) {
|
||||||
mXmppConnectionService.databaseBackend.deleteSignedPreKey(account, signedPreKeyId);
|
mXmppConnectionService.databaseBackend.deleteSignedPreKey(account, signedPreKeyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preVerifyFingerprint(Account account, String name, String fingerprint) {
|
||||||
|
mXmppConnectionService.databaseBackend.storePreVerification(account,name,fingerprint,FingerprintStatus.createInactiveVerified());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class XmppAxolotlSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTrust(FingerprintStatus status) {
|
protected void setTrust(FingerprintStatus status) {
|
||||||
sqLiteAxolotlStore.setFingerprintTrust(getFingerprint(), status);
|
sqLiteAxolotlStore.setFingerprintStatus(getFingerprint(), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FingerprintStatus getTrust() {
|
protected FingerprintStatus getTrust() {
|
||||||
|
|
|
@ -1106,7 +1106,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
identityKeys.add(new IdentityKey(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT), 0));
|
String key = cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY));
|
||||||
|
if (key != null) {
|
||||||
|
identityKeys.add(new IdentityKey(Base64.decode(key, Base64.DEFAULT), 0));
|
||||||
|
} else {
|
||||||
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Missing key (possibly preverified) in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
||||||
|
}
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name);
|
||||||
}
|
}
|
||||||
|
@ -1134,10 +1139,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized) {
|
|
||||||
storeIdentityKey(account, name, own, fingerprint, base64Serialized, FingerprintStatus.createActiveUndecided());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized, FingerprintStatus status) {
|
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();
|
||||||
|
@ -1147,6 +1148,22 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
values.put(SQLiteAxolotlStore.FINGERPRINT, fingerprint);
|
values.put(SQLiteAxolotlStore.FINGERPRINT, fingerprint);
|
||||||
values.put(SQLiteAxolotlStore.KEY, base64Serialized);
|
values.put(SQLiteAxolotlStore.KEY, base64Serialized);
|
||||||
values.putAll(status.toContentValues());
|
values.putAll(status.toContentValues());
|
||||||
|
String where = SQLiteAxolotlStore.ACCOUNT+"=? AND "+SQLiteAxolotlStore.NAME+"=? AND "+SQLiteAxolotlStore.FINGERPRINT+" =?";
|
||||||
|
String[] whereArgs = {account.getUuid(),name,fingerprint};
|
||||||
|
int rows = db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME,values,where,whereArgs);
|
||||||
|
if (rows == 0) {
|
||||||
|
db.insert(SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void storePreVerification(Account account, String name, String fingerprint, FingerprintStatus status) {
|
||||||
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid());
|
||||||
|
values.put(SQLiteAxolotlStore.NAME, name);
|
||||||
|
values.put(SQLiteAxolotlStore.OWN, 0);
|
||||||
|
values.put(SQLiteAxolotlStore.FINGERPRINT, fingerprint);
|
||||||
|
values.putAll(status.toContentValues());
|
||||||
db.insert(SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
db.insert(SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,8 +1244,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeIdentityKey(Account account, String name, IdentityKey identityKey) {
|
public void storeIdentityKey(Account account, String name, IdentityKey identityKey, FingerprintStatus status) {
|
||||||
storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT));
|
storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) {
|
public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) {
|
||||||
|
|
|
@ -65,6 +65,7 @@ import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||||
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.XmppAxolotlMessage;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Blockable;
|
import eu.siacs.conversations.entities.Blockable;
|
||||||
|
@ -102,6 +103,7 @@ import eu.siacs.conversations.utils.PhoneHelper;
|
||||||
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
|
||||||
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
|
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
|
||||||
import eu.siacs.conversations.utils.Xmlns;
|
import eu.siacs.conversations.utils.Xmlns;
|
||||||
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.OnBindListener;
|
import eu.siacs.conversations.xmpp.OnBindListener;
|
||||||
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
|
||||||
|
@ -3608,6 +3610,29 @@ public class XmppConnectionService extends Service {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void verifyFingerprints(Contact contact, List<XmppUri.Fingerprint> fingerprints) {
|
||||||
|
boolean needsRosterWrite = false;
|
||||||
|
final AxolotlService axolotlService = contact.getAccount().getAxolotlService();
|
||||||
|
for(XmppUri.Fingerprint fp : fingerprints) {
|
||||||
|
if (fp.type == XmppUri.FingerprintType.OTR) {
|
||||||
|
needsRosterWrite |= contact.addOtrFingerprint(fp.fingerprint);
|
||||||
|
} else if (fp.type == XmppUri.FingerprintType.OMEMO) {
|
||||||
|
String fingerprint = "05"+fp.fingerprint.replaceAll("\\s","");
|
||||||
|
FingerprintStatus fingerprintStatus = axolotlService.getFingerprintTrust(fingerprint);
|
||||||
|
if (fingerprintStatus != null) {
|
||||||
|
if (!fingerprintStatus.isVerified()) {
|
||||||
|
axolotlService.setFingerprintTrust(fingerprint,fingerprintStatus.toVerified());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
axolotlService.preVerifyFingerprint(contact,fingerprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needsRosterWrite) {
|
||||||
|
syncRosterToDisk(contact.getAccount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnMamPreferencesFetched {
|
public interface OnMamPreferencesFetched {
|
||||||
void onPreferencesFetched(Element prefs);
|
void onPreferencesFetched(Element prefs);
|
||||||
void onPreferencesFetchFailed();
|
void onPreferencesFetchFailed();
|
||||||
|
|
|
@ -397,11 +397,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
protected void showCreateContactDialog(final String prefilledJid, final String fingerprint) {
|
protected void showCreateContactDialog(final String prefilledJid, final Invite invite) {
|
||||||
EnterJidDialog dialog = new EnterJidDialog(
|
EnterJidDialog dialog = new EnterJidDialog(
|
||||||
this, mKnownHosts, mActivatedAccounts,
|
this, mKnownHosts, mActivatedAccounts,
|
||||||
getString(R.string.create_contact), getString(R.string.create),
|
getString(R.string.create_contact), getString(R.string.create),
|
||||||
prefilledJid, null, fingerprint == null
|
prefilledJid, null, !invite.hasFingerprints()
|
||||||
);
|
);
|
||||||
|
|
||||||
dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() {
|
dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() {
|
||||||
|
@ -420,7 +420,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
if (contact.showInRoster()) {
|
if (contact.showInRoster()) {
|
||||||
throw new EnterJidDialog.JidError(getString(R.string.contact_already_exists));
|
throw new EnterJidDialog.JidError(getString(R.string.contact_already_exists));
|
||||||
} else {
|
} else {
|
||||||
contact.addOtrFingerprint(fingerprint);
|
//contact.addOtrFingerprint(fingerprint);
|
||||||
xmppConnectionService.createContact(contact);
|
xmppConnectionService.createContact(contact);
|
||||||
switchToConversation(contact);
|
switchToConversation(contact);
|
||||||
return true;
|
return true;
|
||||||
|
@ -842,6 +842,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleJid(Invite invite) {
|
private boolean handleJid(Invite invite) {
|
||||||
|
Log.d(Config.LOGTAG,"handling invite for "+invite.getJid());
|
||||||
|
for(XmppUri.Fingerprint fp : invite.getFingerprints()) {
|
||||||
|
Log.d(Config.LOGTAG,fp.toString());
|
||||||
|
}
|
||||||
List<Contact> contacts = xmppConnectionService.findContacts(invite.getJid());
|
List<Contact> contacts = xmppConnectionService.findContacts(invite.getJid());
|
||||||
if (invite.isMuc()) {
|
if (invite.isMuc()) {
|
||||||
Conversation muc = xmppConnectionService.findFirstMuc(invite.getJid());
|
Conversation muc = xmppConnectionService.findFirstMuc(invite.getJid());
|
||||||
|
@ -853,16 +857,19 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (contacts.size() == 0) {
|
} else if (contacts.size() == 0) {
|
||||||
showCreateContactDialog(invite.getJid().toString(), invite.getFingerprint());
|
showCreateContactDialog(invite.getJid().toString(), invite);
|
||||||
return false;
|
return false;
|
||||||
} else if (contacts.size() == 1) {
|
} else if (contacts.size() == 1) {
|
||||||
Contact contact = contacts.get(0);
|
Contact contact = contacts.get(0);
|
||||||
if (invite.getFingerprint() != null) {
|
if (invite.hasFingerprints()) {
|
||||||
|
xmppConnectionService.verifyFingerprints(contact,invite.getFingerprints());
|
||||||
|
}
|
||||||
|
/*if (invite.getFingerprint() != null) {
|
||||||
if (contact.addOtrFingerprint(invite.getFingerprint())) {
|
if (contact.addOtrFingerprint(invite.getFingerprint())) {
|
||||||
Log.d(Config.LOGTAG, "added new fingerprint");
|
Log.d(Config.LOGTAG, "added new fingerprint");
|
||||||
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
switchToConversation(contact);
|
switchToConversation(contact);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.OmemoActivity;
|
import eu.siacs.conversations.OmemoActivity;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
|
@ -245,7 +246,9 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
|
||||||
Toast.makeText(TrustKeysActivity.this,R.string.error_fetching_omemo_key,Toast.LENGTH_SHORT).show();
|
Toast.makeText(TrustKeysActivity.this,R.string.error_fetching_omemo_key,Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case SUCCESS_VERIFIED:
|
case SUCCESS_VERIFIED:
|
||||||
Toast.makeText(TrustKeysActivity.this,R.string.verified_omemo_key_with_certificate,Toast.LENGTH_LONG).show();
|
Toast.makeText(TrustKeysActivity.this,
|
||||||
|
Config.X509_VERIFICATION ? R.string.verified_omemo_key_with_certificate : R.string.all_omemo_keys_have_been_verified,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,11 +173,10 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
|
|
||||||
protected boolean verifyWithUri(XmppUri uri) {
|
protected boolean verifyWithUri(XmppUri uri) {
|
||||||
Contact contact = mConversation.getContact();
|
Contact contact = mConversation.getContact();
|
||||||
if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.getFingerprint() != null) {
|
if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.hasFingerprints()) {
|
||||||
contact.addOtrFingerprint(uri.getFingerprint());
|
xmppConnectionService.verifyFingerprints(contact,uri.getFingerprints());
|
||||||
Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show();
|
Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show();
|
||||||
updateView();
|
updateView();
|
||||||
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show();
|
Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show();
|
||||||
|
|
|
@ -4,7 +4,9 @@ import android.net.Uri;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -13,7 +15,9 @@ public class XmppUri {
|
||||||
|
|
||||||
protected String jid;
|
protected String jid;
|
||||||
protected boolean muc;
|
protected boolean muc;
|
||||||
protected String fingerprint;
|
protected List<Fingerprint> fingerprints = new ArrayList<>();
|
||||||
|
|
||||||
|
private static final String OMEMO_URI_PARAM = "omemo-sid-";
|
||||||
|
|
||||||
public XmppUri(String uri) {
|
public XmppUri(String uri) {
|
||||||
try {
|
try {
|
||||||
|
@ -56,7 +60,7 @@ public class XmppUri {
|
||||||
} else {
|
} else {
|
||||||
jid = uri.getSchemeSpecificPart().split("\\?")[0];
|
jid = uri.getSchemeSpecificPart().split("\\?")[0];
|
||||||
}
|
}
|
||||||
fingerprint = parseFingerprint(uri.getQuery());
|
this.fingerprints = parseFingerprints(uri.getQuery());
|
||||||
} else if ("imto".equalsIgnoreCase(scheme)) {
|
} else if ("imto".equalsIgnoreCase(scheme)) {
|
||||||
// sample: imto://xmpp/foo@bar.com
|
// sample: imto://xmpp/foo@bar.com
|
||||||
try {
|
try {
|
||||||
|
@ -73,19 +77,29 @@ public class XmppUri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseFingerprint(String query) {
|
protected List<Fingerprint> parseFingerprints(String query) {
|
||||||
if (query == null) {
|
List<Fingerprint> fingerprints = new ArrayList<>();
|
||||||
return null;
|
String[] pairs = query == null ? new String[0] : query.split(";");
|
||||||
} else {
|
for(String pair : pairs) {
|
||||||
final String NEEDLE = "otr-fingerprint=";
|
String[] parts = pair.split("=",2);
|
||||||
int index = query.indexOf(NEEDLE);
|
if (parts.length == 2) {
|
||||||
if (index >= 0 && query.length() >= (NEEDLE.length() + index + 40)) {
|
String key = parts[0].toLowerCase(Locale.US);
|
||||||
return query.substring(index + NEEDLE.length(), index + NEEDLE.length() + 40);
|
String value = parts[1];
|
||||||
} else {
|
if ("otr-fingerprint".equals(key)) {
|
||||||
return null;
|
fingerprints.add(new Fingerprint(FingerprintType.OTR,value));
|
||||||
|
}
|
||||||
|
if (key.startsWith(OMEMO_URI_PARAM)) {
|
||||||
|
try {
|
||||||
|
int id = Integer.parseInt(key.substring(OMEMO_URI_PARAM.length()));
|
||||||
|
fingerprints.add(new Fingerprint(FingerprintType.OMEMO,value,id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
//ignoring invalid device id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return fingerprints;
|
||||||
|
}
|
||||||
|
|
||||||
public Jid getJid() {
|
public Jid getJid() {
|
||||||
try {
|
try {
|
||||||
|
@ -95,7 +109,36 @@ public class XmppUri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFingerprint() {
|
public List<Fingerprint> getFingerprints() {
|
||||||
return this.fingerprint;
|
return this.fingerprints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFingerprints() {
|
||||||
|
return fingerprints.size() > 0;
|
||||||
|
}
|
||||||
|
public enum FingerprintType {
|
||||||
|
OMEMO,
|
||||||
|
OTR
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Fingerprint {
|
||||||
|
public final FingerprintType type;
|
||||||
|
public final String fingerprint;
|
||||||
|
public final int deviceId;
|
||||||
|
|
||||||
|
public Fingerprint(FingerprintType type, String fingerprint) {
|
||||||
|
this(type, fingerprint, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fingerprint(FingerprintType type, String fingerprint, int deviceId) {
|
||||||
|
this.type = type;
|
||||||
|
this.fingerprint = fingerprint;
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type.toString()+": "+fingerprint+(deviceId != 0 ? " "+String.valueOf(deviceId) : "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -702,4 +702,5 @@
|
||||||
<string name="error_unable_to_create_temporary_file">Unable to create temporary file</string>
|
<string name="error_unable_to_create_temporary_file">Unable to create temporary file</string>
|
||||||
<string name="this_device_has_been_verified">This device has been verified</string>
|
<string name="this_device_has_been_verified">This device has been verified</string>
|
||||||
<string name="copy_fingerprint">Copy fingerprint</string>
|
<string name="copy_fingerprint">Copy fingerprint</string>
|
||||||
|
<string name="all_omemo_keys_have_been_verified">All OMEMO keys have been verified</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue