From 211354ee26f27f24a253ef4e85619435a8f2c942 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 17 Nov 2016 22:28:45 +0100 Subject: [PATCH] put omemo fingerprint in own uri (qr code / nfc) --- .../crypto/axolotl/AxolotlService.java | 8 +++- .../crypto/axolotl/XmppAxolotlSession.java | 2 +- .../siacs/conversations/entities/Account.java | 43 +++++++++++++++++-- .../services/XmppConnectionService.java | 23 ++++++++++ .../ui/StartConversationActivity.java | 16 +++---- .../eu/siacs/conversations/utils/XmppUri.java | 5 ++- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 2ee0501a..702d4ada 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -102,6 +102,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { axolotlStore.preVerifyFingerprint(contact.getAccount(), contact.getJid().toBareJid().toPreppedString(), fingerprint); } + public void preVerifyFingerprint(Account account, String fingerprint) { + axolotlStore.preVerifyFingerprint(account, account.getJid().toBareJid().toPreppedString(), fingerprint); + } + private static class AxolotlAddressMap { protected Map> map; protected final Object MAP_LOCK = new Object(); @@ -293,11 +297,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return new AxolotlAddress(jid.toPreppedString(), 0); } - private Set findOwnSessions() { + public Set findOwnSessions() { AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid()); return new HashSet<>(this.sessions.getAll(ownAddress).values()); } + + private Set findSessionsForContact(Contact contact) { AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); return new HashSet<>(this.sessions.getAll(contactAddress).values()); diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java index b1d071a4..572d62c8 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java @@ -76,7 +76,7 @@ public class XmppAxolotlSession { sqLiteAxolotlStore.setFingerprintStatus(getFingerprint(), status); } - protected FingerprintStatus getTrust() { + public FingerprintStatus getTrust() { FingerprintStatus status = sqLiteAxolotlStore.getFingerprintStatus(getFingerprint()); return (status == null) ? FingerprintStatus.createActiveUndecided() : status; } diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 7d60dcf7..77828b03 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -15,6 +15,7 @@ import org.json.JSONObject; import java.security.PublicKey; import java.security.interfaces.DSAPublicKey; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -24,7 +25,9 @@ import java.util.concurrent.CopyOnWriteArraySet; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrService; import eu.siacs.conversations.crypto.axolotl.AxolotlService; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -599,14 +602,46 @@ public class Account extends AbstractEntity { } public String getShareableUri() { - final String fingerprint = this.getOtrFingerprint(); - if (fingerprint != null) { - return "xmpp:" + this.getJid().toBareJid().toString() + "?otr-fingerprint="+fingerprint; + List fingerprints = this.getFingerprints(); + String uri = "xmpp:"+this.getJid().toBareJid().toString(); + if (fingerprints.size() > 0) { + StringBuilder builder = new StringBuilder(uri); + builder.append('?'); + for(int i = 0; i < fingerprints.size(); ++i) { + XmppUri.FingerprintType type = fingerprints.get(i).type; + if (type == XmppUri.FingerprintType.OMEMO) { + builder.append(XmppUri.OMEMO_URI_PARAM); + builder.append(fingerprints.get(i).deviceId); + } else if (type == XmppUri.FingerprintType.OTR) { + builder.append(XmppUri.OTR_URI_PARAM); + } + builder.append('='); + builder.append(fingerprints.get(i).fingerprint); + if (i != fingerprints.size() -1) { + builder.append(';'); + } + } + return builder.toString(); } else { - return "xmpp:" + this.getJid().toBareJid().toString(); + return uri; } } + private List getFingerprints() { + ArrayList fingerprints = new ArrayList<>(); + final String otr = this.getOtrFingerprint(); + if (otr != null) { + fingerprints.add(new XmppUri.Fingerprint(XmppUri.FingerprintType.OTR,otr)); + } + fingerprints.add(new XmppUri.Fingerprint(XmppUri.FingerprintType.OMEMO,axolotlService.getOwnFingerprint().substring(2),axolotlService.getOwnDeviceId())); + for(XmppAxolotlSession session : axolotlService.findOwnSessions()) { + if (session.getTrust().isVerified() && session.getTrust().isActive()) { + fingerprints.add(new XmppUri.Fingerprint(XmppUri.FingerprintType.OMEMO,session.getFingerprint().substring(2).replaceAll("\\s",""),session.getRemoteAddress().getDeviceId())); + } + } + return fingerprints; + } + public boolean isBlocked(final ListItem contact) { final Jid jid = contact.getJid(); return jid != null && (blocklist.contains(jid.toBareJid()) || blocklist.contains(jid.toDomainJid())); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index dc52e7cf..1321485d 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -67,6 +67,7 @@ import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Blockable; import eu.siacs.conversations.entities.Bookmark; @@ -3633,6 +3634,28 @@ public class XmppConnectionService extends Service { } } + public boolean verifyFingerprints(Account account, List fingerprints) { + final AxolotlService axolotlService = account.getAxolotlService(); + boolean verifiedSomething = false; + for(XmppUri.Fingerprint fp : fingerprints) { + if (fp.type == XmppUri.FingerprintType.OMEMO) { + String fingerprint = "05"+fp.fingerprint.replaceAll("\\s",""); + Log.d(Config.LOGTAG,"trying to verify own fp="+fingerprint); + FingerprintStatus fingerprintStatus = axolotlService.getFingerprintTrust(fingerprint); + if (fingerprintStatus != null) { + if (!fingerprintStatus.isVerified()) { + axolotlService.setFingerprintTrust(fingerprint,fingerprintStatus.toVerified()); + verifiedSomething = true; + } + } else { + axolotlService.preVerifyFingerprint(account,fingerprint); + verifiedSomething = true; + } + } + } + return verifiedSomething; + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); void onPreferencesFetchFailed(); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index b1609adf..2d24fbbf 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -842,9 +842,13 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU } 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()); + Account account = xmppConnectionService.findAccountByJid(invite.getJid()); + if (account != null && invite.hasFingerprints()) { + if (xmppConnectionService.verifyFingerprints(account,invite.getFingerprints())) { + switchToAccount(account); + finish(); + return true; + } } List contacts = xmppConnectionService.findContacts(invite.getJid()); if (invite.isMuc()) { @@ -864,12 +868,6 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU if (invite.hasFingerprints()) { xmppConnectionService.verifyFingerprints(contact,invite.getFingerprints()); } - /*if (invite.getFingerprint() != null) { - if (contact.addOtrFingerprint(invite.getFingerprint())) { - Log.d(Config.LOGTAG, "added new fingerprint"); - xmppConnectionService.syncRosterToDisk(contact.getAccount()); - } - }*/ switchToConversation(contact); return true; } else { diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java index b2dcc553..1fc9812a 100644 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ b/src/main/java/eu/siacs/conversations/utils/XmppUri.java @@ -17,7 +17,8 @@ public class XmppUri { protected boolean muc; protected List fingerprints = new ArrayList<>(); - private static final String OMEMO_URI_PARAM = "omemo-sid-"; + public static final String OMEMO_URI_PARAM = "omemo-sid-"; + public static final String OTR_URI_PARAM = "otr-fingerprint"; public XmppUri(String uri) { try { @@ -85,7 +86,7 @@ public class XmppUri { if (parts.length == 2) { String key = parts[0].toLowerCase(Locale.US); String value = parts[1]; - if ("otr-fingerprint".equals(key)) { + if (OTR_URI_PARAM.equals(key)) { fingerprints.add(new Fingerprint(FingerprintType.OTR,value)); } if (key.startsWith(OMEMO_URI_PARAM)) {