From 4cf4981f1b61d380b324de030554fe57fc7ca98c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 21 Jun 2017 20:52:17 +0200 Subject: [PATCH] combine autocrypt peer state and hand to client app --- .../keychain/remote/OpenPgpService.java | 28 +++--- .../remote/OpenPgpServiceKeyIdExtractor.java | 95 +++++++++++++++---- 2 files changed, 93 insertions(+), 30 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 7eb0d1719..c68e3f9d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -75,6 +75,7 @@ import org.sufficientlysecure.keychain.provider.KeyWritableRepository; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.OverriddenWarningsRepository; +import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.AutocryptState; import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResult; import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResultStatus; import org.sufficientlysecure.keychain.service.BackupKeyringParcel; @@ -306,24 +307,27 @@ public class OpenPgpService extends Service { Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); - switch (keyIdResult.getStatus()) { - case MISSING: { - result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE); - break; - } - case NO_KEYS: - case NO_KEYS_ERROR: { - result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE); - break; - } - case DUPLICATE: { + AutocryptState combinedAutocryptState = keyIdResult.getCombinedAutocryptState(); + if (combinedAutocryptState == null) { + result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE); + return result; + + } + + switch (combinedAutocryptState) { + case GOSSIP: + case RESET: { result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_DISCOURAGE); break; } - case OK: { + case AVAILABLE: { result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_AVAILABLE); break; } + case MUTUAL: { + result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_RECOMMEND); + break; + } default: { throw new IllegalStateException("unhandled case!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceKeyIdExtractor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceKeyIdExtractor.java index 79e4790e6..e87b0aa0e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceKeyIdExtractor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceKeyIdExtractor.java @@ -15,7 +15,7 @@ import android.support.annotation.VisibleForTesting; import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainExternalContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAutocryptPeer; import org.sufficientlysecure.keychain.provider.KeychainExternalContract.EmailStatus; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.Log; @@ -65,7 +65,7 @@ class OpenPgpServiceKeyIdExtractor { for (long keyId : data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS_SELECTED)) { encryptKeyIds.add(keyId); } - result = createKeysOkResult(encryptKeyIds, false); + result = createKeysOkResult(encryptKeyIds, false, null); } else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS) || askIfNoUserIdsProvided) { String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); result = returnKeyIdsFromEmails(data, userIds, callingPackageName); @@ -92,6 +92,7 @@ class OpenPgpServiceKeyIdExtractor { HashSet keyIds = new HashSet<>(); ArrayList missingEmails = new ArrayList<>(); ArrayList duplicateEmails = new ArrayList<>(); + AutocryptState combinedAutocryptState = null; if (hasAddresses) { HashMap userIdEntries = getStatusMapForQueriedAddresses( @@ -104,20 +105,37 @@ class OpenPgpServiceKeyIdExtractor { throw new IllegalStateException("No result for address - shouldn't happen!"); } + if (addressQueryResult.autocryptMasterKeyId != null) { + keyIds.add(addressQueryResult.autocryptMasterKeyId); + + if (addressQueryResult.autocryptKeyStatus != EmailStatus.KEY_STATUS_VERIFIED) { + anyKeyNotVerified = true; + } + + if (combinedAutocryptState == null) { + combinedAutocryptState = addressQueryResult.autocryptState; + } else { + combinedAutocryptState = combinedAutocryptState.combineWith(addressQueryResult.autocryptState); + } + + continue; + } + if (addressQueryResult.uidMasterKeyId != null) { keyIds.add(addressQueryResult.uidMasterKeyId); if (addressQueryResult.uidHasMultipleCandidates) { duplicateEmails.add(queriedAddress); } - } else { - missingEmails.add(queriedAddress); + + if (addressQueryResult.uidKeyStatus != EmailStatus.KEY_STATUS_VERIFIED) { + anyKeyNotVerified = true; + } + continue; } - if (addressQueryResult.uidKeyStatus != EmailStatus.KEY_STATUS_VERIFIED) { - anyKeyNotVerified = true; - } + missingEmails.add(queriedAddress); } if (userIdEntries.size() != encryptionAddresses.length) { @@ -139,7 +157,7 @@ class OpenPgpServiceKeyIdExtractor { return createNoKeysResult(data, keyIds, missingEmails, duplicateEmails); } - return createKeysOkResult(keyIds, allKeysConfirmed); + return createKeysOkResult(keyIds, allKeysConfirmed, combinedAutocryptState); } /** This method queries the KeychainExternalProvider for all addresses given in encryptionUserIds. @@ -169,9 +187,9 @@ class OpenPgpServiceKeyIdExtractor { int autocryptKeyStatus = cursor.getInt(INDEX_AUTOCRYPT_KEY_STATUS); int autocryptPeerStatus = cursor.getInt(INDEX_AUTOCRYPT_PEER_STATE); - AddressQueryResult - status = new AddressQueryResult(uidMasterKeyId, uidKeyStatus, uidHasMultipleCandidates, - autocryptMasterKeyId, autocryptKeyStatus, autocryptPeerStatus); + AddressQueryResult status = new AddressQueryResult( + uidMasterKeyId, uidKeyStatus, uidHasMultipleCandidates, autocryptMasterKeyId, + autocryptKeyStatus, AutocryptState.fromDbValue(autocryptPeerStatus)); keyRows.put(queryAddress, status); } @@ -187,11 +205,10 @@ class OpenPgpServiceKeyIdExtractor { private boolean uidHasMultipleCandidates; private final Long autocryptMasterKeyId; private final int autocryptKeyStatus; - private final int autocryptState; + private final AutocryptState autocryptState; AddressQueryResult(Long uidMasterKeyId, int uidKeyStatus, boolean uidHasMultipleCandidates, Long autocryptMasterKeyId, - int autocryptKeyStatus, - int autocryptState) { + int autocryptKeyStatus, AutocryptState autocryptState) { this.uidMasterKeyId = uidMasterKeyId; this.uidKeyStatus = uidKeyStatus; this.uidHasMultipleCandidates = uidHasMultipleCandidates; @@ -202,7 +219,38 @@ class OpenPgpServiceKeyIdExtractor { } enum AutocryptState { - UNAVAILABLE, DISCOURAGE, AVAILABLE, MUTUAL + RESET, GOSSIP, AVAILABLE, MUTUAL; + + static AutocryptState fromDbValue(int state) { + switch (state) { + case ApiAutocryptPeer.RESET: + return RESET; + case ApiAutocryptPeer.AVAILABLE: + return AVAILABLE; + case ApiAutocryptPeer.GOSSIP: + return GOSSIP; + case ApiAutocryptPeer.MUTUAL: + return MUTUAL; + default: + throw new IllegalStateException(); + } + } + + public AutocryptState combineWith(AutocryptState other) { + if (this == RESET || other == RESET) { + return RESET; + } + if (this == GOSSIP || other == GOSSIP) { + return GOSSIP; + } + if (this == AVAILABLE || other == AVAILABLE) { + return AVAILABLE; + } + if (this == MUTUAL && other == MUTUAL) { + return MUTUAL; + } + throw new IllegalStateException("Bug: autocrypt states can't be combined!"); + } } static class KeyIdResult { @@ -211,6 +259,7 @@ class OpenPgpServiceKeyIdExtractor { private final HashSet mExplicitKeyIds; private final KeyIdResultStatus mStatus; private final boolean mAllKeysConfirmed; + private final AutocryptState mCombinedAutocryptState; private KeyIdResult(PendingIntent keySelectionPendingIntent, KeyIdResultStatus keyIdResultStatus) { mKeySelectionPendingIntent = keySelectionPendingIntent; @@ -218,13 +267,17 @@ class OpenPgpServiceKeyIdExtractor { mAllKeysConfirmed = false; mStatus = keyIdResultStatus; mExplicitKeyIds = null; + mCombinedAutocryptState = null; } - private KeyIdResult(HashSet keyIds, boolean allKeysConfirmed, KeyIdResultStatus keyIdResultStatus) { + + private KeyIdResult(HashSet keyIds, boolean allKeysConfirmed, KeyIdResultStatus keyIdResultStatus, + AutocryptState combinedAutocryptState) { mKeySelectionPendingIntent = null; mUserKeyIds = keyIds; mAllKeysConfirmed = allKeysConfirmed; mStatus = keyIdResultStatus; mExplicitKeyIds = null; + mCombinedAutocryptState = combinedAutocryptState; } private KeyIdResult(KeyIdResult keyIdResult, HashSet explicitKeyIds) { @@ -233,6 +286,7 @@ class OpenPgpServiceKeyIdExtractor { mAllKeysConfirmed = keyIdResult.mAllKeysConfirmed; mStatus = keyIdResult.mStatus; mExplicitKeyIds = explicitKeyIds; + mCombinedAutocryptState = keyIdResult.mCombinedAutocryptState; } boolean hasKeySelectionPendingIntent() { @@ -274,14 +328,19 @@ class OpenPgpServiceKeyIdExtractor { KeyIdResultStatus getStatus() { return mStatus; } + + public AutocryptState getCombinedAutocryptState() { + return mCombinedAutocryptState; + } } enum KeyIdResultStatus { OK, MISSING, DUPLICATE, NO_KEYS, NO_KEYS_ERROR } - private KeyIdResult createKeysOkResult(HashSet encryptKeyIds, boolean allKeysConfirmed) { - return new KeyIdResult(encryptKeyIds, allKeysConfirmed, KeyIdResultStatus.OK); + private KeyIdResult createKeysOkResult(HashSet encryptKeyIds, boolean allKeysConfirmed, + AutocryptState combinedAutocryptState) { + return new KeyIdResult(encryptKeyIds, allKeysConfirmed, KeyIdResultStatus.OK, combinedAutocryptState); } private KeyIdResult createNoKeysResult(Intent data,