combine autocrypt peer state and hand to client app
This commit is contained in:
@@ -75,6 +75,7 @@ import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.OverriddenWarningsRepository;
|
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.KeyIdResult;
|
||||||
import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResultStatus;
|
import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResultStatus;
|
||||||
import org.sufficientlysecure.keychain.service.BackupKeyringParcel;
|
import org.sufficientlysecure.keychain.service.BackupKeyringParcel;
|
||||||
@@ -306,24 +307,27 @@ public class OpenPgpService extends Service {
|
|||||||
Intent result = new Intent();
|
Intent result = new Intent();
|
||||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||||
|
|
||||||
switch (keyIdResult.getStatus()) {
|
AutocryptState combinedAutocryptState = keyIdResult.getCombinedAutocryptState();
|
||||||
case MISSING: {
|
if (combinedAutocryptState == null) {
|
||||||
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE);
|
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE);
|
||||||
break;
|
return result;
|
||||||
}
|
|
||||||
case NO_KEYS:
|
}
|
||||||
case NO_KEYS_ERROR: {
|
|
||||||
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_UNAVAILABLE);
|
switch (combinedAutocryptState) {
|
||||||
break;
|
case GOSSIP:
|
||||||
}
|
case RESET: {
|
||||||
case DUPLICATE: {
|
|
||||||
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_DISCOURAGE);
|
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_DISCOURAGE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OK: {
|
case AVAILABLE: {
|
||||||
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_AVAILABLE);
|
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_AVAILABLE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MUTUAL: {
|
||||||
|
result.putExtra(OpenPgpApi.RESULT_AUTOCRYPT_STATUS, OpenPgpApi.AUTOCRYPT_STATUS_RECOMMEND);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new IllegalStateException("unhandled case!");
|
throw new IllegalStateException("unhandled case!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import android.support.annotation.VisibleForTesting;
|
|||||||
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
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.provider.KeychainExternalContract.EmailStatus;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@@ -65,7 +65,7 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
for (long keyId : data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS_SELECTED)) {
|
for (long keyId : data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS_SELECTED)) {
|
||||||
encryptKeyIds.add(keyId);
|
encryptKeyIds.add(keyId);
|
||||||
}
|
}
|
||||||
result = createKeysOkResult(encryptKeyIds, false);
|
result = createKeysOkResult(encryptKeyIds, false, null);
|
||||||
} else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS) || askIfNoUserIdsProvided) {
|
} else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS) || askIfNoUserIdsProvided) {
|
||||||
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
|
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
|
||||||
result = returnKeyIdsFromEmails(data, userIds, callingPackageName);
|
result = returnKeyIdsFromEmails(data, userIds, callingPackageName);
|
||||||
@@ -92,6 +92,7 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
HashSet<Long> keyIds = new HashSet<>();
|
HashSet<Long> keyIds = new HashSet<>();
|
||||||
ArrayList<String> missingEmails = new ArrayList<>();
|
ArrayList<String> missingEmails = new ArrayList<>();
|
||||||
ArrayList<String> duplicateEmails = new ArrayList<>();
|
ArrayList<String> duplicateEmails = new ArrayList<>();
|
||||||
|
AutocryptState combinedAutocryptState = null;
|
||||||
|
|
||||||
if (hasAddresses) {
|
if (hasAddresses) {
|
||||||
HashMap<String, AddressQueryResult> userIdEntries = getStatusMapForQueriedAddresses(
|
HashMap<String, AddressQueryResult> userIdEntries = getStatusMapForQueriedAddresses(
|
||||||
@@ -104,20 +105,37 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
throw new IllegalStateException("No result for address - shouldn't happen!");
|
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) {
|
if (addressQueryResult.uidMasterKeyId != null) {
|
||||||
keyIds.add(addressQueryResult.uidMasterKeyId);
|
keyIds.add(addressQueryResult.uidMasterKeyId);
|
||||||
|
|
||||||
if (addressQueryResult.uidHasMultipleCandidates) {
|
if (addressQueryResult.uidHasMultipleCandidates) {
|
||||||
duplicateEmails.add(queriedAddress);
|
duplicateEmails.add(queriedAddress);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
missingEmails.add(queriedAddress);
|
if (addressQueryResult.uidKeyStatus != EmailStatus.KEY_STATUS_VERIFIED) {
|
||||||
|
anyKeyNotVerified = true;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressQueryResult.uidKeyStatus != EmailStatus.KEY_STATUS_VERIFIED) {
|
missingEmails.add(queriedAddress);
|
||||||
anyKeyNotVerified = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userIdEntries.size() != encryptionAddresses.length) {
|
if (userIdEntries.size() != encryptionAddresses.length) {
|
||||||
@@ -139,7 +157,7 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
return createNoKeysResult(data, keyIds, missingEmails, duplicateEmails);
|
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.
|
/** 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 autocryptKeyStatus = cursor.getInt(INDEX_AUTOCRYPT_KEY_STATUS);
|
||||||
int autocryptPeerStatus = cursor.getInt(INDEX_AUTOCRYPT_PEER_STATE);
|
int autocryptPeerStatus = cursor.getInt(INDEX_AUTOCRYPT_PEER_STATE);
|
||||||
|
|
||||||
AddressQueryResult
|
AddressQueryResult status = new AddressQueryResult(
|
||||||
status = new AddressQueryResult(uidMasterKeyId, uidKeyStatus, uidHasMultipleCandidates,
|
uidMasterKeyId, uidKeyStatus, uidHasMultipleCandidates, autocryptMasterKeyId,
|
||||||
autocryptMasterKeyId, autocryptKeyStatus, autocryptPeerStatus);
|
autocryptKeyStatus, AutocryptState.fromDbValue(autocryptPeerStatus));
|
||||||
|
|
||||||
keyRows.put(queryAddress, status);
|
keyRows.put(queryAddress, status);
|
||||||
}
|
}
|
||||||
@@ -187,11 +205,10 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
private boolean uidHasMultipleCandidates;
|
private boolean uidHasMultipleCandidates;
|
||||||
private final Long autocryptMasterKeyId;
|
private final Long autocryptMasterKeyId;
|
||||||
private final int autocryptKeyStatus;
|
private final int autocryptKeyStatus;
|
||||||
private final int autocryptState;
|
private final AutocryptState autocryptState;
|
||||||
|
|
||||||
AddressQueryResult(Long uidMasterKeyId, int uidKeyStatus, boolean uidHasMultipleCandidates, Long autocryptMasterKeyId,
|
AddressQueryResult(Long uidMasterKeyId, int uidKeyStatus, boolean uidHasMultipleCandidates, Long autocryptMasterKeyId,
|
||||||
int autocryptKeyStatus,
|
int autocryptKeyStatus, AutocryptState autocryptState) {
|
||||||
int autocryptState) {
|
|
||||||
this.uidMasterKeyId = uidMasterKeyId;
|
this.uidMasterKeyId = uidMasterKeyId;
|
||||||
this.uidKeyStatus = uidKeyStatus;
|
this.uidKeyStatus = uidKeyStatus;
|
||||||
this.uidHasMultipleCandidates = uidHasMultipleCandidates;
|
this.uidHasMultipleCandidates = uidHasMultipleCandidates;
|
||||||
@@ -202,7 +219,38 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum AutocryptState {
|
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 {
|
static class KeyIdResult {
|
||||||
@@ -211,6 +259,7 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
private final HashSet<Long> mExplicitKeyIds;
|
private final HashSet<Long> mExplicitKeyIds;
|
||||||
private final KeyIdResultStatus mStatus;
|
private final KeyIdResultStatus mStatus;
|
||||||
private final boolean mAllKeysConfirmed;
|
private final boolean mAllKeysConfirmed;
|
||||||
|
private final AutocryptState mCombinedAutocryptState;
|
||||||
|
|
||||||
private KeyIdResult(PendingIntent keySelectionPendingIntent, KeyIdResultStatus keyIdResultStatus) {
|
private KeyIdResult(PendingIntent keySelectionPendingIntent, KeyIdResultStatus keyIdResultStatus) {
|
||||||
mKeySelectionPendingIntent = keySelectionPendingIntent;
|
mKeySelectionPendingIntent = keySelectionPendingIntent;
|
||||||
@@ -218,13 +267,17 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
mAllKeysConfirmed = false;
|
mAllKeysConfirmed = false;
|
||||||
mStatus = keyIdResultStatus;
|
mStatus = keyIdResultStatus;
|
||||||
mExplicitKeyIds = null;
|
mExplicitKeyIds = null;
|
||||||
|
mCombinedAutocryptState = null;
|
||||||
}
|
}
|
||||||
private KeyIdResult(HashSet<Long> keyIds, boolean allKeysConfirmed, KeyIdResultStatus keyIdResultStatus) {
|
|
||||||
|
private KeyIdResult(HashSet<Long> keyIds, boolean allKeysConfirmed, KeyIdResultStatus keyIdResultStatus,
|
||||||
|
AutocryptState combinedAutocryptState) {
|
||||||
mKeySelectionPendingIntent = null;
|
mKeySelectionPendingIntent = null;
|
||||||
mUserKeyIds = keyIds;
|
mUserKeyIds = keyIds;
|
||||||
mAllKeysConfirmed = allKeysConfirmed;
|
mAllKeysConfirmed = allKeysConfirmed;
|
||||||
mStatus = keyIdResultStatus;
|
mStatus = keyIdResultStatus;
|
||||||
mExplicitKeyIds = null;
|
mExplicitKeyIds = null;
|
||||||
|
mCombinedAutocryptState = combinedAutocryptState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyIdResult(KeyIdResult keyIdResult, HashSet<Long> explicitKeyIds) {
|
private KeyIdResult(KeyIdResult keyIdResult, HashSet<Long> explicitKeyIds) {
|
||||||
@@ -233,6 +286,7 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
mAllKeysConfirmed = keyIdResult.mAllKeysConfirmed;
|
mAllKeysConfirmed = keyIdResult.mAllKeysConfirmed;
|
||||||
mStatus = keyIdResult.mStatus;
|
mStatus = keyIdResult.mStatus;
|
||||||
mExplicitKeyIds = explicitKeyIds;
|
mExplicitKeyIds = explicitKeyIds;
|
||||||
|
mCombinedAutocryptState = keyIdResult.mCombinedAutocryptState;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasKeySelectionPendingIntent() {
|
boolean hasKeySelectionPendingIntent() {
|
||||||
@@ -274,14 +328,19 @@ class OpenPgpServiceKeyIdExtractor {
|
|||||||
KeyIdResultStatus getStatus() {
|
KeyIdResultStatus getStatus() {
|
||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AutocryptState getCombinedAutocryptState() {
|
||||||
|
return mCombinedAutocryptState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum KeyIdResultStatus {
|
enum KeyIdResultStatus {
|
||||||
OK, MISSING, DUPLICATE, NO_KEYS, NO_KEYS_ERROR
|
OK, MISSING, DUPLICATE, NO_KEYS, NO_KEYS_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyIdResult createKeysOkResult(HashSet<Long> encryptKeyIds, boolean allKeysConfirmed) {
|
private KeyIdResult createKeysOkResult(HashSet<Long> encryptKeyIds, boolean allKeysConfirmed,
|
||||||
return new KeyIdResult(encryptKeyIds, allKeysConfirmed, KeyIdResultStatus.OK);
|
AutocryptState combinedAutocryptState) {
|
||||||
|
return new KeyIdResult(encryptKeyIds, allKeysConfirmed, KeyIdResultStatus.OK, combinedAutocryptState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyIdResult createNoKeysResult(Intent data,
|
private KeyIdResult createNoKeysResult(Intent data,
|
||||||
|
|||||||
Reference in New Issue
Block a user