From 54f1422d3d076b7e96cf2c03c61cf75affaf43e7 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 18 Nov 2016 22:38:07 +0100 Subject: put omemo fingerprint in own uri (qr code / nfc) --- .../messenger/crypto/axolotl/AxolotlService.java | 6 +- .../crypto/axolotl/XmppAxolotlSession.java | 2 +- .../java/de/pixart/messenger/entities/Account.java | 167 +++++++++++++-------- .../messenger/services/XmppConnectionService.java | 22 +++ .../messenger/ui/StartConversationActivity.java | 16 +- .../java/de/pixart/messenger/utils/XmppUri.java | 5 +- 6 files changed, 139 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java b/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java index 807ede503..532fbe470 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java +++ b/src/main/java/de/pixart/messenger/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,7 +297,7 @@ 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()); } diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlSession.java index c71ad92a9..566afef9a 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/XmppAxolotlSession.java +++ b/src/main/java/de/pixart/messenger/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/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java index eca0733cf..7a94750ab 100644 --- a/src/main/java/de/pixart/messenger/entities/Account.java +++ b/src/main/java/de/pixart/messenger/entities/Account.java @@ -13,6 +13,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; @@ -23,7 +24,9 @@ import de.pixart.messenger.R; import de.pixart.messenger.crypto.OtrService; import de.pixart.messenger.crypto.PgpDecryptionService; import de.pixart.messenger.crypto.axolotl.AxolotlService; +import de.pixart.messenger.crypto.axolotl.XmppAxolotlSession; import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.utils.XmppUri; import de.pixart.messenger.xmpp.XmppConnection; import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; @@ -90,16 +93,16 @@ public class Account extends AbstractEntity { return pgpDecryptionService != null && pgpDecryptionService.isConnected(); } - public boolean setShowErrorNotification(boolean newValue) { - boolean oldValue = showErrorNotification(); - setKey("show_error",Boolean.toString(newValue)); - return newValue != oldValue; - } + public boolean setShowErrorNotification(boolean newValue) { + boolean oldValue = showErrorNotification(); + setKey("show_error",Boolean.toString(newValue)); + return newValue != oldValue; + } - public boolean showErrorNotification() { - String key = getKey("show_error"); - return key == null || Boolean.parseBoolean(key); - } + public boolean showErrorNotification() { + String key = getKey("show_error"); + return key == null || Boolean.parseBoolean(key); + } public enum State { DISABLED, @@ -237,13 +240,13 @@ public class Account extends AbstractEntity { this.password = password; this.options = options; this.rosterVersion = rosterVersion; - JSONObject tmp; + JSONObject tmp; try { - tmp = new JSONObject(keys); + tmp = new JSONObject(keys); } catch (JSONException e) { - tmp = new JSONObject(); + tmp = new JSONObject(); } - this.keys = tmp; + this.keys = tmp; this.avatar = avatar; this.displayName = displayName; this.hostname = hostname; @@ -289,12 +292,12 @@ public class Account extends AbstractEntity { return jid.getLocalpart(); } - public boolean setJid(final Jid next) { - final Jid prev = this.jid != null ? this.jid.toBareJid() : null; - this.jid = next; - return prev == null || (next != null && !prev.equals(next.toBareJid()) - ); - } + public boolean setJid(final Jid next) { + final Jid prev = this.jid != null ? this.jid.toBareJid() : null; + this.jid = next; + return prev == null || (next != null && !prev.equals(next.toBareJid()) + ); + } public Jid getServer() { return jid.toDomainJid(); @@ -393,32 +396,32 @@ public class Account extends AbstractEntity { } public String getKey(final String name) { - synchronized (this.keys) { - return this.keys.optString(name, null); - } + synchronized (this.keys) { + return this.keys.optString(name, null); + } } - public int getKeyAsInt(final String name, int defaultValue) { - String key = getKey(name); - try { - return key == null ? defaultValue : Integer.parseInt(key); - } catch (NumberFormatException e) { - return defaultValue; + public int getKeyAsInt(final String name, int defaultValue) { + String key = getKey(name); + try { + return key == null ? defaultValue : Integer.parseInt(key); + } catch (NumberFormatException e) { + return defaultValue; } } - public boolean setKey(final String keyName, final String keyValue) { - synchronized (this.keys) { - try { - this.keys.put(keyName, keyValue); - return true; - } catch (final JSONException e) { - return false; - } - } - } + public boolean setKey(final String keyName, final String keyValue) { + synchronized (this.keys) { + try { + this.keys.put(keyName, keyValue); + return true; + } catch (final JSONException e) { + return false; + } + } + } - public boolean setPrivateKeyAlias(String alias) { + public boolean setPrivateKeyAlias(String alias) { return setKey("private_key_alias", alias); } @@ -434,9 +437,9 @@ public class Account extends AbstractEntity { values.put(SERVER, jid.getDomainpart()); values.put(PASSWORD, password); values.put(OPTIONS, options); - synchronized (this.keys) { - values.put(KEYS, this.keys.toString()); - } + synchronized (this.keys) { + values.put(KEYS, this.keys.toString()); + } values.put(ROSTERVERSION, rosterVersion); values.put(AVATAR, avatar); values.put(DISPLAY_NAME, displayName); @@ -513,41 +516,41 @@ public class Account extends AbstractEntity { } public String getPgpSignature() { - return getKey(KEY_PGP_SIGNATURE); + return getKey(KEY_PGP_SIGNATURE); } public boolean setPgpSignature(String signature) { - return setKey(KEY_PGP_SIGNATURE, signature); + return setKey(KEY_PGP_SIGNATURE, signature); } public boolean unsetPgpSignature() { - synchronized (this.keys) { - return keys.remove(KEY_PGP_SIGNATURE) != null; - } + synchronized (this.keys) { + return keys.remove(KEY_PGP_SIGNATURE) != null; + } } public long getPgpId() { - synchronized (this.keys) { - if (keys.has(KEY_PGP_ID)) { - try { - return keys.getLong(KEY_PGP_ID); - } catch (JSONException e) { - return 0; - } - } else { + synchronized (this.keys) { + if (keys.has(KEY_PGP_ID)) { + try { + return keys.getLong(KEY_PGP_ID); + } catch (JSONException e) { + return 0; + } + } else { return 0; } } } public boolean setPgpSignId(long pgpID) { - synchronized (this.keys) { - try { - keys.put(KEY_PGP_ID, pgpID); - } catch (JSONException e) { - return false; - } - return true; + synchronized (this.keys) { + try { + keys.put(KEY_PGP_ID, pgpID); + } catch (JSONException e) { + return false; + } + return true; } } @@ -599,12 +602,44 @@ 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) { diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 5fb90d822..92b288494 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -3771,6 +3771,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/de/pixart/messenger/ui/StartConversationActivity.java b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java index 83ab06b62..cd64149cd 100644 --- a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java +++ b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java @@ -841,9 +841,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()) { @@ -863,12 +867,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/de/pixart/messenger/utils/XmppUri.java b/src/main/java/de/pixart/messenger/utils/XmppUri.java index 31ba694ff..dc52f6637 100644 --- a/src/main/java/de/pixart/messenger/utils/XmppUri.java +++ b/src/main/java/de/pixart/messenger/utils/XmppUri.java @@ -17,7 +17,8 @@ public class XmppUri { protected boolean muc; protected String fingerprint; 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 { @@ -90,7 +91,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)) { -- cgit v1.2.3