mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-25 07:51:48 -05:00
Better error handling for passphrase cache if key is missing
This commit is contained in:
parent
e4c8674792
commit
38da2af0e8
@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
@ -163,7 +164,8 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface PassphraseCache {
|
public interface PassphraseCache {
|
||||||
public String getCachedPassphrase(long masterKeyId);
|
public String getCachedPassphrase(long masterKeyId)
|
||||||
|
throws NoSecretKeyException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InvalidDataException extends Exception {
|
public static class InvalidDataException extends Exception {
|
||||||
|
@ -168,8 +168,7 @@ public class OpenPgpService extends RemoteService {
|
|||||||
}
|
}
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||||
Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
|
return getPassphraseBundleIntent(data, accSettings.getKeyId());
|
||||||
return passphraseBundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Input- and OutputStream from ParcelFileDescriptor
|
// Get Input- and OutputStream from ParcelFileDescriptor
|
||||||
@ -289,8 +288,7 @@ public class OpenPgpService extends RemoteService {
|
|||||||
}
|
}
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||||
Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());
|
return getPassphraseBundleIntent(data, accSettings.getKeyId());
|
||||||
return passphraseBundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign and encrypt
|
// sign and encrypt
|
||||||
@ -358,9 +356,13 @@ public class OpenPgpService extends RemoteService {
|
|||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PgpDecryptVerify.PassphraseCache() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) {
|
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
||||||
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
OpenPgpService.this, masterKeyId);
|
OpenPgpService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PgpDecryptVerify.NoSecretKeyException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputData, os
|
inputData, os
|
||||||
|
@ -307,9 +307,13 @@ public class KeychainIntentService extends IntentService
|
|||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PgpDecryptVerify.PassphraseCache() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) {
|
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
||||||
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
KeychainIntentService.this, masterKeyId);
|
KeychainIntentService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PgpDecryptVerify.NoSecretKeyException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputData, outStream
|
inputData, outStream
|
||||||
@ -351,9 +355,13 @@ public class KeychainIntentService extends IntentService
|
|||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PgpDecryptVerify.PassphraseCache() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) {
|
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
||||||
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
KeychainIntentService.this, masterKeyId);
|
KeychainIntentService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PgpDecryptVerify.NoSecretKeyException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputData, null
|
inputData, null
|
||||||
|
@ -76,12 +76,24 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
private static final int NOTIFICATION_ID = 1;
|
private static final int NOTIFICATION_ID = 1;
|
||||||
|
|
||||||
|
private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1;
|
||||||
|
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND = 2;
|
||||||
|
|
||||||
private BroadcastReceiver mIntentReceiver;
|
private BroadcastReceiver mIntentReceiver;
|
||||||
|
|
||||||
private LongSparseArray<CachedPassphrase> mPassphraseCache = new LongSparseArray<CachedPassphrase>();
|
private LongSparseArray<CachedPassphrase> mPassphraseCache = new LongSparseArray<CachedPassphrase>();
|
||||||
|
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
|
public static class KeyNotFoundException extends Exception {
|
||||||
|
public KeyNotFoundException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyNotFoundException(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This caches a new passphrase in memory by sending a new command to the service. An android
|
* This caches a new passphrase in memory by sending a new command to the service. An android
|
||||||
* service is only run once. Thus, when the service is already started, new commands just add
|
* service is only run once. Thus, when the service is already started, new commands just add
|
||||||
@ -114,24 +126,23 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @param keyId
|
* @param keyId
|
||||||
* @return passphrase or null (if no passphrase is cached for this keyId)
|
* @return passphrase or null (if no passphrase is cached for this keyId)
|
||||||
*/
|
*/
|
||||||
public static String getCachedPassphrase(Context context, long keyId) {
|
public static String getCachedPassphrase(Context context, long keyId) throws KeyNotFoundException {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() get masterKeyId for " + keyId);
|
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() get masterKeyId for " + keyId);
|
||||||
|
|
||||||
Intent intent = new Intent(context, PassphraseCacheService.class);
|
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||||
intent.setAction(ACTION_PASSPHRASE_CACHE_GET);
|
intent.setAction(ACTION_PASSPHRASE_CACHE_GET);
|
||||||
|
|
||||||
final Object mutex = new Object();
|
final Object mutex = new Object();
|
||||||
final Bundle returnBundle = new Bundle();
|
final Message returnMessage = Message.obtain();
|
||||||
|
|
||||||
HandlerThread handlerThread = new HandlerThread("getPassphraseThread");
|
HandlerThread handlerThread = new HandlerThread("getPassphraseThread");
|
||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
Handler returnHandler = new Handler(handlerThread.getLooper()) {
|
Handler returnHandler = new Handler(handlerThread.getLooper()) {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
if (message.obj != null) {
|
// copy over result to handle after mutex.wait
|
||||||
String passphrase = ((Bundle) message.obj).getString(EXTRA_PASSPHRASE);
|
returnMessage.what = message.what;
|
||||||
returnBundle.putString(EXTRA_PASSPHRASE, passphrase);
|
returnMessage.copyFrom(message);
|
||||||
}
|
|
||||||
synchronized (mutex) {
|
synchronized (mutex) {
|
||||||
mutex.notify();
|
mutex.notify();
|
||||||
}
|
}
|
||||||
@ -155,10 +166,13 @@ public class PassphraseCacheService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnBundle.containsKey(EXTRA_PASSPHRASE)) {
|
switch (returnMessage.what) {
|
||||||
return returnBundle.getString(EXTRA_PASSPHRASE);
|
case MSG_PASSPHRASE_CACHE_GET_OKAY:
|
||||||
} else {
|
return returnMessage.getData().getString(EXTRA_PASSPHRASE);
|
||||||
return null;
|
case MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND:
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
default:
|
||||||
|
throw new KeyNotFoundException("should not happen!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +182,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @param keyId
|
* @param keyId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private String getCachedPassphraseImpl(long keyId) {
|
private String getCachedPassphraseImpl(long keyId) throws ProviderHelper.NotFoundException {
|
||||||
// passphrase for symmetric encryption?
|
// passphrase for symmetric encryption?
|
||||||
if (keyId == Constants.key.symmetric) {
|
if (keyId == Constants.key.symmetric) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
|
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
|
||||||
@ -181,7 +195,6 @@ public class PassphraseCacheService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to get master key id which is used as an identifier for cached passphrases
|
// try to get master key id which is used as an identifier for cached passphrases
|
||||||
try {
|
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for masterKeyId " + keyId);
|
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for masterKeyId " + keyId);
|
||||||
CanonicalizedSecretKeyRing key = new ProviderHelper(this).getCanonicalizedSecretKeyRing(
|
CanonicalizedSecretKeyRing key = new ProviderHelper(this).getCanonicalizedSecretKeyRing(
|
||||||
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId));
|
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId));
|
||||||
@ -209,11 +222,6 @@ public class PassphraseCacheService extends Service {
|
|||||||
Log.d(Constants.TAG, "PassphraseCacheService: Cache passphrase again when getting it!");
|
Log.d(Constants.TAG, "PassphraseCacheService: Cache passphrase again when getting it!");
|
||||||
addCachedPassphrase(this, keyId, cachedPassphrase.getPassphrase(), cachedPassphrase.getPrimaryUserID());
|
addCachedPassphrase(this, keyId, cachedPassphrase.getPassphrase(), cachedPassphrase.getPrimaryUserID());
|
||||||
return cachedPassphrase.getPassphrase();
|
return cachedPassphrase.getPassphrase();
|
||||||
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.e(Constants.TAG, "PassphraseCacheService: Passphrase for unknown key was requested!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,12 +303,19 @@ public class PassphraseCacheService extends Service {
|
|||||||
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
||||||
|
|
||||||
String passphrase = getCachedPassphraseImpl(keyId);
|
|
||||||
|
|
||||||
Message msg = Message.obtain();
|
Message msg = Message.obtain();
|
||||||
|
try {
|
||||||
|
String passphrase = getCachedPassphraseImpl(keyId);
|
||||||
|
msg.what = MSG_PASSPHRASE_CACHE_GET_OKAY;
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(EXTRA_PASSPHRASE, passphrase);
|
bundle.putString(EXTRA_PASSPHRASE, passphrase);
|
||||||
msg.obj = bundle;
|
msg.setData(bundle);
|
||||||
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
|
Log.e(Constants.TAG, "PassphraseCacheService: Passphrase for unknown key was requested!");
|
||||||
|
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
messenger.send(msg);
|
messenger.send(msg);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
|
@ -231,7 +231,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements
|
|||||||
*/
|
*/
|
||||||
private void initiateCertifying() {
|
private void initiateCertifying() {
|
||||||
// get the user's passphrase for this key (if required)
|
// get the user's passphrase for this key (if required)
|
||||||
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
|
String passphrase = null;
|
||||||
|
try {
|
||||||
|
passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
Log.e(Constants.TAG, "Key not found!", e);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
PassphraseDialogFragment.show(this, mMasterKeyId,
|
PassphraseDialogFragment.show(this, mMasterKeyId,
|
||||||
new Handler() {
|
new Handler() {
|
||||||
|
@ -475,8 +475,14 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void cachePassphraseForEdit() {
|
private void cachePassphraseForEdit() {
|
||||||
|
try {
|
||||||
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
|
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
|
||||||
mSaveKeyringParcel.mMasterKeyId);
|
mSaveKeyringParcel.mMasterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
Log.e(Constants.TAG, "Key not found!", e);
|
||||||
|
getActivity().finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mCurrentPassphrase == null) {
|
if (mCurrentPassphrase == null) {
|
||||||
PassphraseDialogFragment.show(getActivity(), mSaveKeyringParcel.mMasterKeyId,
|
PassphraseDialogFragment.show(getActivity(), mSaveKeyringParcel.mMasterKeyId,
|
||||||
new Handler() {
|
new Handler() {
|
||||||
|
@ -450,6 +450,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
if (mSigningKeyId != 0 && PassphraseCacheService.getCachedPassphrase(this, mSigningKeyId) == null) {
|
if (mSigningKeyId != 0 && PassphraseCacheService.getCachedPassphrase(this, mSigningKeyId) == null) {
|
||||||
PassphraseDialogFragment.show(this, mSigningKeyId,
|
PassphraseDialogFragment.show(this, mSigningKeyId,
|
||||||
new Handler() {
|
new Handler() {
|
||||||
@ -465,6 +466,9 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
Log.e(Constants.TAG, "Key not found!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user