From 6a853f4c84e66aee70e3e1cd784ddbb8c1deac00 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 23 Feb 2016 17:08:17 +0100 Subject: wip --- .../keychain/remote/OpenPgpService.java | 130 ++++++++++++++------- 1 file changed, 88 insertions(+), 42 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java') 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 91d3cda7c..10b137b4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -18,6 +18,17 @@ package org.sufficientlysecure.keychain.remote; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; + import android.app.PendingIntent; import android.app.Service; import android.content.Intent; @@ -42,6 +53,8 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing.UserId; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; @@ -60,18 +73,9 @@ import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashSet; -import java.util.List; - public class OpenPgpService extends Service { - static final String[] EMAIL_SEARCH_PROJECTION = new String[]{ + static final String[] KEY_SEARCH_PROJECTION = new String[]{ KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.IS_EXPIRED, @@ -79,7 +83,7 @@ public class OpenPgpService extends Service { }; // do not pre-select revoked or expired keys - static final String EMAIL_SEARCH_WHERE = Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED + static final String KEY_SEARCH_WHERE = Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; private ApiPermissionHelper mApiPermissionHelper; @@ -94,22 +98,35 @@ public class OpenPgpService extends Service { mApiDao = new ApiDataAccessObject(this); } - /** - * Search database for key ids based on emails. - */ - private Intent returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { + private static class KeyIdResult { + final Intent mRequiredUserInteraction; + final HashSet mKeyIds; + + KeyIdResult(Intent requiredUserInteraction) { + mRequiredUserInteraction = requiredUserInteraction; + mKeyIds = null; + } + KeyIdResult(HashSet keyIds) { + mRequiredUserInteraction = null; + mKeyIds = keyIds; + } + } + + private KeyIdResult returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0); boolean missingUserIdsCheck = false; boolean duplicateUserIdsCheck = false; - ArrayList keyIds = new ArrayList<>(); + HashSet keyIds = new HashSet<>(); ArrayList missingEmails = new ArrayList<>(); ArrayList duplicateEmails = new ArrayList<>(); if (!noUserIdsCheck) { - for (String email : encryptionUserIds) { + for (String rawUserId : encryptionUserIds) { + UserId userId = KeyRing.splitUserId(rawUserId); + String email = userId.email != null ? userId.email : rawUserId; // try to find the key for this specific email Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); - Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); + Cursor cursor = getContentResolver().query(uri, KEY_SEARCH_PROJECTION, KEY_SEARCH_WHERE, null, null); try { // result should be one entry containing the key id if (cursor != null && cursor.moveToFirst()) { @@ -138,15 +155,11 @@ public class OpenPgpService extends Service { } } - // convert ArrayList to long[] - long[] keyIdsArray = new long[keyIds.size()]; - for (int i = 0; i < keyIdsArray.length; i++) { - keyIdsArray[i] = keyIds.get(i); - } - if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) { // allow the user to verify pub key selection + // convert ArrayList to long[] + long[] keyIdsArray = getUnboxedLongArray(keyIds); ApiPendingIntentFactory piFactory = new ApiPendingIntentFactory(getBaseContext()); PendingIntent pi = piFactory.createSelectPublicKeyPendingIntent(data, keyIdsArray, missingEmails, duplicateEmails, noUserIdsCheck); @@ -155,18 +168,15 @@ public class OpenPgpService extends Service { Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_INTENT, pi); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; + return new KeyIdResult(result); } else { // everything was easy, we have exactly one key for every email - if (keyIdsArray.length == 0) { + if (keyIds.isEmpty()) { Log.e(Constants.TAG, "keyIdsArray.length == 0, should never happen!"); } - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIdsArray); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); - return result; + return new KeyIdResult(keyIds); } } @@ -281,20 +291,31 @@ public class OpenPgpService extends Service { compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED; } - // first try to get key ids from non-ambiguous key id extra - long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); - if (keyIds == null) { + long[] keyIds; + { + HashSet encryptKeyIds = new HashSet<>(); + // get key ids based on given user ids - String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); - // give params through to activity... - Intent result = returnKeyIdsFromEmails(data, userIds); + if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) { + String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); + data.removeExtra(OpenPgpApi.EXTRA_USER_IDS); + // give params through to activity... + KeyIdResult result = returnKeyIdsFromEmails(data, userIds); + + if (result.mRequiredUserInteraction != null) { + return result.mRequiredUserInteraction; + } + encryptKeyIds.addAll(result.mKeyIds); + } - if (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0) == OpenPgpApi.RESULT_CODE_SUCCESS) { - keyIds = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS); - } else { - // if not success -> result contains a PendingIntent for user interaction - return result; + // add key ids from non-ambiguous key id extra + if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) { + for (long keyId : data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)) { + encryptKeyIds.add(keyId); + } } + + keyIds = getUnboxedLongArray(encryptKeyIds); } // TODO this is not correct! @@ -670,8 +691,33 @@ public class OpenPgpService extends Service { } else { // get key ids based on given user ids String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); - return returnKeyIdsFromEmails(data, userIds); + data.removeExtra(OpenPgpApi.EXTRA_USER_IDS); + KeyIdResult keyResult = returnKeyIdsFromEmails(data, userIds); + if (keyResult.mRequiredUserInteraction != null) { + return keyResult.mRequiredUserInteraction; + } + + if (keyResult.mKeyIds == null) { + throw new AssertionError("one of requiredUserInteraction and keyIds must be non-null, this is a bug!"); + } + + long[] keyIds = getUnboxedLongArray(keyResult.mKeyIds); + + Intent resultIntent = new Intent(); + resultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); + resultIntent.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIds); + return resultIntent; + } + } + + @NonNull + private static long[] getUnboxedLongArray(@NonNull Collection arrayList) { + long[] result = new long[arrayList.size()]; + int i = 0; + for (Long e : arrayList) { + result[i++] = e; } + return result; } private Intent checkPermissionImpl(@NonNull Intent data) { -- cgit v1.2.3