From 774c806f460204505491db47f9481103da187e8d Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Thu, 19 May 2016 12:04:01 +0800 Subject: Added passphrase check for stripped masterkeys --- .../keychain/ui/BackupRestoreFragment.java | 75 ++++++++++++++++------ 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupRestoreFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupRestoreFragment.java index 3ff3bfbe3..4a1e4937d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupRestoreFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupRestoreFragment.java @@ -17,7 +17,7 @@ package org.sufficientlysecure.keychain.ui; -import java.util.ArrayList; +import java.util.*; import android.app.Activity; import android.content.ContentResolver; @@ -35,17 +35,17 @@ import android.view.ViewGroup; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.FileHelper; public class BackupRestoreFragment extends Fragment { - // This ids for multiple key export. - private ArrayList mIdsForRepeatAskPassphrase; - // This index for remembering the number of master key. - private int mIndex; + // masterKeyId & subKeyId for multi-key export + private Iterator> mIdsForRepeatAskPassphrase; private static final int REQUEST_REPEAT_PASSPHRASE = 0x00007002; private static final int REQUEST_CODE_INPUT = 0x00007003; @@ -93,10 +93,10 @@ public class BackupRestoreFragment extends Fragment { return; } - new AsyncTask>() { + new AsyncTask>() { @Override - protected ArrayList doInBackground(ContentResolver... resolver) { - ArrayList askPassphraseIds = new ArrayList<>(); + protected HashMap doInBackground(ContentResolver... resolver) { + HashMap askPassphraseIds = new HashMap<>(); Cursor cursor = resolver[0].query( KeyRings.buildUnifiedKeyRingsUri(), new String[]{ KeyRings.MASTER_KEY_ID, @@ -109,13 +109,20 @@ public class BackupRestoreFragment extends Fragment { switch (secretKeyType) { // all of these make no sense to ask case PASSPHRASE_EMPTY: - case GNU_DUMMY: case DIVERT_TO_CARD: case UNAVAILABLE: continue; + case GNU_DUMMY: { + Long masterKeyId = cursor.getLong(0); + Long subKeyId = getFirstSubKeyWithPassphrase(masterKeyId, resolver[0]); + if(subKeyId != null) { + askPassphraseIds.put(masterKeyId, subKeyId); + } + continue; + } default: { - long keyId = cursor.getLong(0); - askPassphraseIds.add(keyId); + long masterKeyId = cursor.getLong(0); + askPassphraseIds.put(masterKeyId, masterKeyId); } } } @@ -128,18 +135,48 @@ public class BackupRestoreFragment extends Fragment { return askPassphraseIds; } + private Long getFirstSubKeyWithPassphrase(long masterKeyId, ContentResolver resolver) { + Cursor cursor = resolver.query( + KeychainContract.Keys.buildKeysUri(masterKeyId), new String[]{ + Keys.KEY_ID, + Keys.HAS_SECRET, + }, Keys.HAS_SECRET + " != 0", null, null); + try { + if (cursor != null) { + while(cursor.moveToNext()) { + SecretKeyType secretKeyType = SecretKeyType.fromNum(cursor.getInt(1)); + switch (secretKeyType) { + case PASSPHRASE_EMPTY: + case DIVERT_TO_CARD: + case UNAVAILABLE: + return null; + case GNU_DUMMY: + continue; + default: { + return cursor.getLong(0); + } + } + } + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + @Override - protected void onPostExecute(ArrayList askPassphraseIds) { + protected void onPostExecute(HashMap askPassphraseIds) { super.onPostExecute(askPassphraseIds); FragmentActivity activity = getActivity(); if (activity == null) { return; } - mIdsForRepeatAskPassphrase = askPassphraseIds; - mIndex = 0; + mIdsForRepeatAskPassphrase = askPassphraseIds.entrySet().iterator(); - if (mIdsForRepeatAskPassphrase.size() != 0) { + if (mIdsForRepeatAskPassphrase.hasNext()) { startPassphraseActivity(); return; } @@ -157,9 +194,11 @@ public class BackupRestoreFragment extends Fragment { } Intent intent = new Intent(activity, PassphraseDialogActivity.class); - long masterKeyId = mIdsForRepeatAskPassphrase.get(mIndex++); + Map.Entry keyPair = mIdsForRepeatAskPassphrase.next(); + long masterKeyId = keyPair.getKey(); + long subKeyId = keyPair.getValue(); RequiredInputParcel requiredInput = - RequiredInputParcel.createRequiredDecryptPassphrase(masterKeyId, masterKeyId); + RequiredInputParcel.createRequiredDecryptPassphrase(masterKeyId, subKeyId); requiredInput.mSkipCaching = true; intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput); startActivityForResult(intent, REQUEST_REPEAT_PASSPHRASE); @@ -172,7 +211,7 @@ public class BackupRestoreFragment extends Fragment { if (resultCode != Activity.RESULT_OK) { return; } - if (mIndex < mIdsForRepeatAskPassphrase.size()) { + if (mIdsForRepeatAskPassphrase.hasNext()) { startPassphraseActivity(); return; } -- cgit v1.2.3