From 2ea902a081cb028bd7c708b80fdd73cc7f33f566 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 10 Jan 2021 15:38:08 +0100 Subject: [PATCH] Differentiate between ikey and manual trusts --- .../detail/AccountDetailsFragment.java | 2 +- .../detail/ContactDetailFragment.java | 2 +- .../ToggleableFingerprintsAdapter.java | 10 +++- .../main/res/drawable/ic_lock_black_24dp.xml | 9 ++++ .../data/repository/RxIkeyRepository.java | 6 --- .../store/crypto/IkeyAwareOpenPgpStore.java | 51 +++++-------------- .../contact/ContactDetailViewModel.java | 6 ++- .../openpgp/FingerprintViewItem.java | 2 +- 8 files changed, 37 insertions(+), 51 deletions(-) create mode 100644 app/src/main/res/drawable/ic_lock_black_24dp.xml diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/account/detail/AccountDetailsFragment.java b/app/src/main/java/org/mercury_im/messenger/android/ui/account/detail/AccountDetailsFragment.java index d4bd202..651cc13 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/account/detail/AccountDetailsFragment.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/account/detail/AccountDetailsFragment.java @@ -106,7 +106,7 @@ public class AccountDetailsFragment extends Fragment { viewModel = new ViewModelProvider(this, factory) .get(AndroidAccountDetailsViewModel.class); - this.otherFingerprintsAdapter = new ToggleableFingerprintsAdapter(this::markFingerprintTrusted); + this.otherFingerprintsAdapter = new ToggleableFingerprintsAdapter(context, this::markFingerprintTrusted); this.otherFingerprintsAdapter.setItemLongClickListener(fingerprint -> viewModel.unpublishPublicKey(fingerprint)); } diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/contacts/detail/ContactDetailFragment.java b/app/src/main/java/org/mercury_im/messenger/android/ui/contacts/detail/ContactDetailFragment.java index 2a28316..8f2b9b4 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/contacts/detail/ContactDetailFragment.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/contacts/detail/ContactDetailFragment.java @@ -114,7 +114,7 @@ public class ContactDetailFragment extends Fragment { contactName.setOnClickListener(v -> displayChangeContactNameDialog()); - fingerprintsAdapter = new ToggleableFingerprintsAdapter( + fingerprintsAdapter = new ToggleableFingerprintsAdapter(getContext(), (fingerprint, checked) -> viewModel.markDeviceFingerprintTrusted(fingerprint, checked)); fingerprintRecyclerView.setAdapter(fingerprintsAdapter); diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/openpgp/ToggleableFingerprintsAdapter.java b/app/src/main/java/org/mercury_im/messenger/android/ui/openpgp/ToggleableFingerprintsAdapter.java index e4727b1..c5e8d37 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/openpgp/ToggleableFingerprintsAdapter.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/openpgp/ToggleableFingerprintsAdapter.java @@ -1,5 +1,7 @@ package org.mercury_im.messenger.android.ui.openpgp; +import android.content.Context; +import android.os.Build; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -9,6 +11,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.mercury_im.messenger.R; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem; import org.pgpainless.key.OpenPgpV4Fingerprint; @@ -25,8 +28,10 @@ public class ToggleableFingerprintsAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.LOLLIPOP) { + holder.trustSwitch.setThumbDrawable(context.getDrawable(R.drawable.ic_lock_black_24dp)); + } holder.divider.setVisibility(position == fingerprints.size() - 1 ? View.GONE : View.VISIBLE); holder.itemView.setOnLongClickListener(v -> { diff --git a/app/src/main/res/drawable/ic_lock_black_24dp.xml b/app/src/main/res/drawable/ic_lock_black_24dp.xml new file mode 100644 index 0000000..67a7c73 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/data/src/main/java/org/mercury_im/messenger/data/repository/RxIkeyRepository.java b/data/src/main/java/org/mercury_im/messenger/data/repository/RxIkeyRepository.java index 9396f6b..a88fdac 100644 --- a/data/src/main/java/org/mercury_im/messenger/data/repository/RxIkeyRepository.java +++ b/data/src/main/java/org/mercury_im/messenger/data/repository/RxIkeyRepository.java @@ -150,11 +150,8 @@ public class RxIkeyRepository implements IkeyRepository { public Completable storeRecord(UUID accountId, EntityBareJid jid, IkeyRecord record) { assert jid.equals(record.getJid()); return getRecordModel(accountId, jid, false) - .doOnNext(m -> LOGGER.log(Level.INFO, "Loaded model: " + m)) .single(new IkeyRecordModel()) - .doOnSuccess(m -> LOGGER.log(Level.INFO, "Singled model: " + m)) .map(m -> { - LOGGER.log(Level.INFO, "Mapping model: " + m); if (m.getId() == null) m.setId(UUID.randomUUID()); m.setAccountId(accountId); m.setJid(jid); @@ -174,14 +171,11 @@ public class RxIkeyRepository implements IkeyRepository { sm.setUri(s.getUri()); m.getSubordinates().add(sm); } - LOGGER.log(Level.INFO, "Return model: " + m); return m; }) .flatMap(data::upsert) - .doOnSuccess(m -> LOGGER.log(Level.INFO, "Upserting model: " + m)) .ignoreElement() - .doOnComplete(() -> LOGGER.log(Level.INFO, "Updated model")) .doOnError(e -> LOGGER.log(Level.SEVERE, "Error storing ikey record", e)); } diff --git a/domain/src/main/java/org/mercury_im/messenger/core/store/crypto/IkeyAwareOpenPgpStore.java b/domain/src/main/java/org/mercury_im/messenger/core/store/crypto/IkeyAwareOpenPgpStore.java index 0278f6a..67148fb 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/store/crypto/IkeyAwareOpenPgpStore.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/store/crypto/IkeyAwareOpenPgpStore.java @@ -1,6 +1,6 @@ package org.mercury_im.messenger.core.store.crypto; -import org.jivesoftware.smackx.ikey.mechanism.IkeyType; +import org.jivesoftware.smackx.ikey.record.IkeyRecord; import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpTrustStore; import org.jxmpp.jid.BareJid; import org.jxmpp.jid.EntityBareJid; @@ -10,7 +10,6 @@ import org.mercury_im.messenger.core.data.repository.IkeyKeyRepository; import org.mercury_im.messenger.core.data.repository.IkeyRecordRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpTrustRepository; -import org.mercury_im.messenger.core.util.Optional; import org.pgpainless.key.OpenPgpV4Fingerprint; import java.io.IOException; @@ -19,10 +18,9 @@ import java.util.logging.Level; import java.util.logging.Logger; import io.reactivex.Completable; -import io.reactivex.Observable; +import io.reactivex.Maybe; import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.subjects.BehaviorSubject; public class IkeyAwareOpenPgpStore extends MercuryOpenPgpStore { @@ -56,7 +54,6 @@ public class IkeyAwareOpenPgpStore extends MercuryOpenPgpStore { private final SchedulersFacade schedulers; private final CompositeDisposable disposable = new CompositeDisposable(); - private final BehaviorSubject accountIsIkeyAware = BehaviorSubject.createDefault(false); public TrustStore(UUID accountId, OpenPgpTrustRepository openPgpTrustRepository, IkeyKeyRepository ikeyKeyRepository, IkeyRecordRepository ikeyRecordRepository, SchedulersFacade schedulersFacade) { this.accountId = accountId; @@ -64,27 +61,24 @@ public class IkeyAwareOpenPgpStore extends MercuryOpenPgpStore { this.ikeyKeyRepository = ikeyKeyRepository; this.ikeyRecordRepository = ikeyRecordRepository; this.schedulers = schedulersFacade; - - accountIsIkeyAware().subscribe(accountIsIkeyAware); } @Override protected Trust readTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException { EntityBareJid jid = owner.asEntityBareJidOrThrow(); - Trust trust = accountIsIkeyAware.firstOrError() - .flatMap(isAware -> isAware ? - readIkeyTrust(jid, fingerprint) : - readManualTrust(jid, fingerprint)) + Trust trust = readIkeyTrust(jid, fingerprint) .blockingGet(); return trust == null ? Trust.undecided : trust; } private Single readIkeyTrust(EntityBareJid owner, OpenPgpV4Fingerprint fingerprint) { return ikeyRecordRepository.loadRecord(accountId, owner) - .map(record -> record.hasSubordinate(fingerprint) ? - record.getTrust() : Trust.undecided) - .doOnNext(trust -> LOGGER.log(Level.INFO, "Read ikey trust " + trust + " for device key " + fingerprint + " of contact " + owner)) + .filter(record -> record.getTrust() == Trust.trusted) + .filter(record -> record.hasSubordinate(fingerprint)) + .map(IkeyRecord::getTrust) + .map(trust -> trust == Trust.trusted ? Trust.ikey_trusted : trust) .firstElement() + .flatMap(t -> t == Trust.undecided ? readManualTrust(owner, fingerprint).toMaybe() : Maybe.just(t)) .switchIfEmpty(readManualTrust(owner, fingerprint)); } @@ -103,31 +97,10 @@ public class IkeyAwareOpenPgpStore extends MercuryOpenPgpStore { protected void writeTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException { EntityBareJid jid = owner.asEntityBareJidOrThrow(); disposable.add( - contactHasIkeyRecord(owner.asEntityBareJidIfPossible()) - .flatMapCompletable(hasRecord -> hasRecord && accountIsIkeyAware.getValue() ? - skipManualTrustForIkeyContact(jid, fingerprint, trust) : - writeManualTrust(jid, fingerprint, trust)) - .compose(schedulers.executeUiSafeCompletable()) - .subscribe(() -> {}, - e -> LOGGER.log(Level.SEVERE, "An error happened while marking device key " + fingerprint + " of " + jid + " as " + trust, e))); - } - - private Completable skipManualTrustForIkeyContact(EntityBareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) { - return Completable.complete() - .doOnComplete(() -> LOGGER.log(Level.INFO, - "Contact " + owner + " has an Ikey Record, so do not mark " + fingerprint + " as " + trust)); - } - - private Single contactHasIkeyRecord(EntityBareJid owner) { - return ikeyRecordRepository.loadRecord(accountId, owner.asEntityBareJidOrThrow()) - .isEmpty() - .map(resultEmpty -> !resultEmpty); // negate - } - - protected Observable accountIsIkeyAware() { - return ikeyKeyRepository.loadSecretKey(accountId) - .map(Optional::isPresent) - .compose(schedulers.executeUiSafeObservable()); + writeManualTrust(jid, fingerprint, trust) + .compose(schedulers.executeUiSafeCompletable()) + .subscribe(() -> {}, + e -> LOGGER.log(Level.SEVERE, "An error happened while marking device key " + fingerprint + " of " + jid + " as " + trust, e))); } } } diff --git a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/contact/ContactDetailViewModel.java b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/contact/ContactDetailViewModel.java index f0a246b..7c3fa45 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/contact/ContactDetailViewModel.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/contact/ContactDetailViewModel.java @@ -7,6 +7,7 @@ import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterGroup; import org.jivesoftware.smackx.ox.OpenPgpManager; +import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider; import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jxmpp.jid.EntityBareJid; @@ -100,8 +101,9 @@ public class ContactDetailViewModel implements MercuryViewModel { } public Completable init(Peer peer) { - this.openPgpStore = OpenPgpManager.getInstanceFor(connectionManager.getConnection(peer.getAccount().getId()).getConnection()) - .getOpenPgpProvider().getStore(); + OpenPgpManager openPgpManager = OpenPgpManager.getInstanceFor(connectionManager.getConnection(peer.getAccount().getId()).getConnection()); + OpenPgpProvider provider = openPgpManager.getOpenPgpProvider(); + this.openPgpStore = provider.getStore(); return Completable.fromAction(() -> { this.peerId = peer.getId(); diff --git a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/openpgp/FingerprintViewItem.java b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/openpgp/FingerprintViewItem.java index ed2764e..22a8344 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/openpgp/FingerprintViewItem.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/openpgp/FingerprintViewItem.java @@ -23,6 +23,6 @@ public class FingerprintViewItem { OpenPgpTrustStore.Trust trusted; public boolean isTrusted() { - return trusted == OpenPgpTrustStore.Trust.trusted; + return trusted == OpenPgpTrustStore.Trust.trusted || trusted == OpenPgpTrustStore.Trust.ikey_trusted; } }