diff options
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service')
4 files changed, 0 insertions, 1522 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java deleted file mode 100644 index 1c6aa7971..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ /dev/null @@ -1,905 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.service; - -import android.app.IntentService; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; - -import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPUtil; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.FileHelper; -import org.sufficientlysecure.keychain.helper.OtherHelper; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; -import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpImportExport; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; -import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; -import org.sufficientlysecure.keychain.util.HkpKeyServer; -import org.sufficientlysecure.keychain.util.InputData; -import org.sufficientlysecure.keychain.util.KeychainServiceListener; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; -import org.sufficientlysecure.keychain.util.ProgressScaler; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * This Service contains all important long lasting operations for APG. It receives Intents with - * data from the activities or other apps, queues these intents, executes them, and stops itself - * after doing them. - */ -public class KeychainIntentService extends IntentService - implements ProgressDialogUpdater, KeychainServiceListener { - - /* extras that can be given by intent */ - public static final String EXTRA_MESSENGER = "messenger"; - public static final String EXTRA_DATA = "data"; - - /* possible actions */ - public static final String ACTION_ENCRYPT_SIGN = Constants.INTENT_PREFIX + "ENCRYPT_SIGN"; - - public static final String ACTION_DECRYPT_VERIFY = Constants.INTENT_PREFIX + "DECRYPT_VERIFY"; - - public static final String ACTION_SAVE_KEYRING = Constants.INTENT_PREFIX + "SAVE_KEYRING"; - public static final String ACTION_GENERATE_KEY = Constants.INTENT_PREFIX + "GENERATE_KEY"; - public static final String ACTION_GENERATE_DEFAULT_RSA_KEYS = Constants.INTENT_PREFIX - + "GENERATE_DEFAULT_RSA_KEYS"; - - public static final String ACTION_DELETE_FILE_SECURELY = Constants.INTENT_PREFIX - + "DELETE_FILE_SECURELY"; - - public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING"; - public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING"; - - public static final String ACTION_UPLOAD_KEYRING = Constants.INTENT_PREFIX + "UPLOAD_KEYRING"; - public static final String ACTION_DOWNLOAD_AND_IMPORT_KEYS = Constants.INTENT_PREFIX + "QUERY_KEYRING"; - - public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; - - /* keys for data bundle */ - - // encrypt, decrypt, import export - public static final String TARGET = "target"; - // possible targets: - public static final int TARGET_BYTES = 1; - public static final int TARGET_URI = 2; - - // encrypt - public static final String ENCRYPT_SIGNATURE_KEY_ID = "secret_key_id"; - public static final String ENCRYPT_USE_ASCII_ARMOR = "use_ascii_armor"; - public static final String ENCRYPT_ENCRYPTION_KEYS_IDS = "encryption_keys_ids"; - public static final String ENCRYPT_COMPRESSION_ID = "compression_id"; - public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes"; - public static final String ENCRYPT_INPUT_FILE = "input_file"; - public static final String ENCRYPT_OUTPUT_FILE = "output_file"; - public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase"; - - // decrypt/verify - public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; - public static final String DECRYPT_PASSPHRASE = "passphrase"; - - // save keyring - public static final String SAVE_KEYRING_PARCEL = "save_parcel"; - public static final String SAVE_KEYRING_CAN_SIGN = "can_sign"; - - - // generate key - public static final String GENERATE_KEY_ALGORITHM = "algorithm"; - public static final String GENERATE_KEY_KEY_SIZE = "key_size"; - public static final String GENERATE_KEY_SYMMETRIC_PASSPHRASE = "passphrase"; - public static final String GENERATE_KEY_MASTER_KEY = "master_key"; - - // delete file securely - public static final String DELETE_FILE = "deleteFile"; - - // import key - public static final String IMPORT_KEY_LIST = "import_key_list"; - - // export key - public static final String EXPORT_OUTPUT_STREAM = "export_output_stream"; - public static final String EXPORT_FILENAME = "export_filename"; - public static final String EXPORT_SECRET = "export_secret"; - public static final String EXPORT_ALL = "export_all"; - public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "export_key_ring_id"; - - // upload key - public static final String UPLOAD_KEY_SERVER = "upload_key_server"; - - // query key - public static final String DOWNLOAD_KEY_SERVER = "query_key_server"; - public static final String DOWNLOAD_KEY_LIST = "query_key_id"; - - // sign key - public static final String CERTIFY_KEY_MASTER_KEY_ID = "sign_key_master_key_id"; - public static final String CERTIFY_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; - public static final String CERTIFY_KEY_UIDS = "sign_key_uids"; - - /* - * possible data keys as result send over messenger - */ - // keys - public static final String RESULT_NEW_KEY = "new_key"; - public static final String RESULT_KEY_USAGES = "new_key_usages"; - - // encrypt - public static final String RESULT_BYTES = "encrypted_data"; - - // decrypt/verify - public static final String RESULT_DECRYPTED_BYTES = "decrypted_data"; - public static final String RESULT_DECRYPT_VERIFY_RESULT = "signature"; - - // import - public static final String RESULT_IMPORT_ADDED = "added"; - public static final String RESULT_IMPORT_UPDATED = "updated"; - public static final String RESULT_IMPORT_BAD = "bad"; - - // export - public static final String RESULT_EXPORT = "exported"; - - Messenger mMessenger; - - private boolean mIsCanceled; - - public KeychainIntentService() { - super("KeychainIntentService"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - this.mIsCanceled = true; - } - - /** - * The IntentService calls this method from the default worker thread with the intent that - * started the service. When this method returns, IntentService stops the service, as - * appropriate. - */ - @Override - protected void onHandleIntent(Intent intent) { - Bundle extras = intent.getExtras(); - if (extras == null) { - Log.e(Constants.TAG, "Extras bundle is null!"); - return; - } - - if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || (intent - .getAction() == null))) { - Log.e(Constants.TAG, - "Extra bundle must contain a messenger, a data bundle, and an action!"); - return; - } - - Uri dataUri = intent.getData(); - - mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); - Bundle data = extras.getBundle(EXTRA_DATA); - - OtherHelper.logDebugBundle(data, "EXTRA_DATA"); - - String action = intent.getAction(); - - // executeServiceMethod action from extra bundle - if (ACTION_ENCRYPT_SIGN.equals(action)) { - try { - /* Input */ - int target = data.getInt(TARGET); - - long signatureKeyId = data.getLong(ENCRYPT_SIGNATURE_KEY_ID); - String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE); - - boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR); - long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS); - int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID); - InputStream inStream; - long inLength; - InputData inputData; - OutputStream outStream; -// String streamFilename = null; - switch (target) { - case TARGET_BYTES: /* encrypting bytes directly */ - byte[] bytes = data.getByteArray(ENCRYPT_MESSAGE_BYTES); - - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; - - inputData = new InputData(inStream, inLength); - outStream = new ByteArrayOutputStream(); - - break; - case TARGET_URI: /* encrypting file */ - String inputFile = data.getString(ENCRYPT_INPUT_FILE); - String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); - - // check if storage is ready - if (!FileHelper.isStorageMounted(inputFile) - || !FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException( - getString(R.string.error_external_storage_not_ready)); - } - - inStream = new FileInputStream(inputFile); - File file = new File(inputFile); - inLength = file.length(); - inputData = new InputData(inStream, inLength); - - outStream = new FileOutputStream(outputFile); - - break; - - // TODO: not used currently -// case TARGET_STREAM: /* Encrypting stream from content uri */ -// Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); -// -// // InputStream -// InputStream in = getContentResolver().openInputStream(providerUri); -// inLength = PgpHelper.getLengthOfStream(in); -// inputData = new InputData(in, inLength); -// -// // OutputStream -// try { -// while (true) { -// streamFilename = PgpHelper.generateRandomFilename(32); -// if (streamFilename == null) { -// throw new PgpGeneralException("couldn't generate random file name"); -// } -// openFileInput(streamFilename).close(); -// } -// } catch (FileNotFoundException e) { -// // found a name that isn't used yet -// } -// outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); -// -// break; - - default: - throw new PgpGeneralException("No target choosen!"); - - } - - /* Operation */ - PgpSignEncrypt.Builder builder = - new PgpSignEncrypt.Builder(this, inputData, outStream); - builder.progress(this); - - builder.enableAsciiArmorOutput(useAsciiArmor) - .compressionId(compressionId) - .symmetricEncryptionAlgorithm( - Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) - .signatureForceV3(Preferences.getPreferences(this).getForceV3Signatures()) - .encryptionKeyIds(encryptionKeyIds) - .symmetricPassphrase(symmetricPassphrase) - .signatureKeyId(signatureKeyId) - .signatureHashAlgorithm( - Preferences.getPreferences(this).getDefaultHashAlgorithm()) - .signaturePassphrase( - PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)); - - builder.build().execute(); - - outStream.close(); - - /* Output */ - - Bundle resultData = new Bundle(); - - switch (target) { - case TARGET_BYTES: - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - - resultData.putByteArray(RESULT_BYTES, output); - - break; - case TARGET_URI: - // nothing, file was written, just send okay - - break; -// case TARGET_STREAM: -// String uri = DataStream.buildDataStreamUri(streamFilename).toString(); -// resultData.putString(RESULT_URI, uri); -// -// break; - } - - OtherHelper.logDebugBundle(resultData, "resultData"); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_DECRYPT_VERIFY.equals(action)) { - try { - /* Input */ - int target = data.getInt(TARGET); - - byte[] bytes = data.getByteArray(DECRYPT_CIPHERTEXT_BYTES); - String passphrase = data.getString(DECRYPT_PASSPHRASE); - - InputStream inStream; - long inLength; - InputData inputData; - OutputStream outStream; - String streamFilename = null; - switch (target) { - case TARGET_BYTES: /* decrypting bytes directly */ - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; - - inputData = new InputData(inStream, inLength); - outStream = new ByteArrayOutputStream(); - - break; - - case TARGET_URI: /* decrypting file */ - String inputFile = data.getString(ENCRYPT_INPUT_FILE); - String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); - - // check if storage is ready - if (!FileHelper.isStorageMounted(inputFile) - || !FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException( - getString(R.string.error_external_storage_not_ready)); - } - - // InputStream - inLength = -1; - inStream = new FileInputStream(inputFile); - File file = new File(inputFile); - inLength = file.length(); - inputData = new InputData(inStream, inLength); - - // OutputStream - outStream = new FileOutputStream(outputFile); - - break; - - // TODO: not used, maybe contains code useful for new decrypt method for files? -// case TARGET_STREAM: /* decrypting stream from content uri */ -// Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); -// -// // InputStream -// InputStream in = getContentResolver().openInputStream(providerUri); -// inLength = PgpHelper.getLengthOfStream(in); -// inputData = new InputData(in, inLength); -// -// // OutputStream -// try { -// while (true) { -// streamFilename = PgpHelper.generateRandomFilename(32); -// if (streamFilename == null) { -// throw new PgpGeneralException("couldn't generate random file name"); -// } -// openFileInput(streamFilename).close(); -// } -// } catch (FileNotFoundException e) { -// // found a name that isn't used yet -// } -// outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); -// -// break; - - default: - throw new PgpGeneralException("No target choosen!"); - - } - - /* Operation */ - - Bundle resultData = new Bundle(); - - // verifyText and decrypt returning additional resultData values for the - // verification of signatures - PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, outStream); - builder.progressDialogUpdater(this); - - builder.allowSymmetricDecryption(true) - .passphrase(passphrase); - - PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); - - outStream.close(); - - resultData.putParcelable(RESULT_DECRYPT_VERIFY_RESULT, decryptVerifyResult); - - /* Output */ - - switch (target) { - case TARGET_BYTES: - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - resultData.putByteArray(RESULT_DECRYPTED_BYTES, output); - break; - case TARGET_URI: - // nothing, file was written, just send okay and verification bundle - - break; -// case TARGET_STREAM: -// String uri = DataStream.buildDataStreamUri(streamFilename).toString(); -// resultData.putString(RESULT_URI, uri); -// -// break; - } - - OtherHelper.logDebugBundle(resultData, "resultData"); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_SAVE_KEYRING.equals(action)) { - try { - /* Input */ - SaveKeyringParcel saveParams = data.getParcelable(SAVE_KEYRING_PARCEL); - String oldPassphrase = saveParams.oldPassphrase; - String newPassphrase = saveParams.newPassphrase; - boolean canSign = true; - - if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) { - canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN); - } - - if (newPassphrase == null) { - newPassphrase = oldPassphrase; - } - - long masterKeyId = saveParams.keys.get(0).getKeyID(); - - /* Operation */ - if (!canSign) { - PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 50, 100)); - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); - keyRing = keyOperations.changeSecretKeyPassphrase(keyRing, - oldPassphrase, newPassphrase); - setProgress(R.string.progress_saving_key_ring, 50, 100); - ProviderHelper.saveKeyRing(this, keyRing); - setProgress(R.string.progress_done, 100, 100); - } else { - PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); - PGPSecretKeyRing privkey = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); - PGPPublicKeyRing pubkey = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId); - PgpKeyOperation.Pair<PGPSecretKeyRing,PGPPublicKeyRing> pair = - keyOperations.buildSecretKey(privkey, pubkey, saveParams); - setProgress(R.string.progress_saving_key_ring, 90, 100); - // save the pair - ProviderHelper.saveKeyRing(this, pair.second, pair.first); - setProgress(R.string.progress_done, 100, 100); - } - PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase); - - /* Output */ - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_GENERATE_KEY.equals(action)) { - try { - /* Input */ - int algorithm = data.getInt(GENERATE_KEY_ALGORITHM); - String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE); - int keysize = data.getInt(GENERATE_KEY_KEY_SIZE); - boolean masterKey = data.getBoolean(GENERATE_KEY_MASTER_KEY); - - /* Operation */ - PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPSecretKey newKey = keyOperations.createKey(algorithm, keysize, - passphrase, masterKey); - - /* Output */ - Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyToBytes(newKey)); - - OtherHelper.logDebugBundle(resultData, "resultData"); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_GENERATE_DEFAULT_RSA_KEYS.equals(action)) { - // generate one RSA 4096 key for signing and one subkey for encrypting! - try { - /* Input */ - String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE); - ArrayList<PGPSecretKey> newKeys = new ArrayList<PGPSecretKey>(); - ArrayList<Integer> keyUsageList = new ArrayList<Integer>(); - - /* Operation */ - int keysTotal = 3; - int keysCreated = 0; - setProgress( - getApplicationContext().getResources(). - getQuantityString(R.plurals.progress_generating, keysTotal), - keysCreated, - keysTotal); - PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - - PGPSecretKey masterKey = keyOperations.createKey(Id.choice.algorithm.rsa, - 4096, passphrase, true); - newKeys.add(masterKey); - keyUsageList.add(KeyFlags.CERTIFY_OTHER); - keysCreated++; - setProgress(keysCreated, keysTotal); - - PGPSecretKey subKey = keyOperations.createKey(Id.choice.algorithm.rsa, - 4096, passphrase, false); - newKeys.add(subKey); - keyUsageList.add(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE); - keysCreated++; - setProgress(keysCreated, keysTotal); - - subKey = keyOperations.createKey(Id.choice.algorithm.rsa, - 4096, passphrase, false); - newKeys.add(subKey); - keyUsageList.add(KeyFlags.SIGN_DATA); - keysCreated++; - setProgress(keysCreated, keysTotal); - - // TODO: default to one master for cert, one sub for encrypt and one sub - // for sign - - /* Output */ - - Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyArrayListToBytes(newKeys)); - resultData.putIntegerArrayList(RESULT_KEY_USAGES, keyUsageList); - - OtherHelper.logDebugBundle(resultData, "resultData"); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_DELETE_FILE_SECURELY.equals(action)) { - try { - /* Input */ - String deleteFile = data.getString(DELETE_FILE); - - /* Operation */ - try { - PgpHelper.deleteFileSecurely(this, this, new File(deleteFile)); - } catch (FileNotFoundException e) { - throw new PgpGeneralException( - getString(R.string.error_file_not_found, deleteFile)); - } catch (IOException e) { - throw new PgpGeneralException(getString(R.string.error_file_delete_failed, - deleteFile)); - } - - /* Output */ - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_IMPORT_KEYRING.equals(action)) { - try { - List<ImportKeysListEntry> entries = data.getParcelableArrayList(IMPORT_KEY_LIST); - - Bundle resultData = new Bundle(); - - PgpImportExport pgpImportExport = new PgpImportExport(this, this); - resultData = pgpImportExport.importKeyRings(entries); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_EXPORT_KEYRING.equals(action)) { - try { - - boolean exportSecret = data.getBoolean(EXPORT_SECRET, false); - long[] masterKeyIds = data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID); - String outputFile = data.getString(EXPORT_FILENAME); - - // If not exporting all keys get the masterKeyIds of the keys to export from the intent - boolean exportAll = data.getBoolean(EXPORT_ALL); - - // check if storage is ready - if (!FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready)); - } - - ArrayList<Long> publicMasterKeyIds = new ArrayList<Long>(); - ArrayList<Long> secretMasterKeyIds = new ArrayList<Long>(); - - String selection = null; - if(!exportAll) { - selection = KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID + " IN( "; - for(long l : masterKeyIds) { - selection += Long.toString(l) + ","; - } - selection = selection.substring(0, selection.length()-1) + " )"; - } - - Cursor cursor = getContentResolver().query(KeyRings.buildUnifiedKeyRingsUri(), - new String[]{ KeyRings.MASTER_KEY_ID, KeyRings.HAS_SECRET }, - selection, null, null); - try { - cursor.moveToFirst(); - do { - // export public either way - publicMasterKeyIds.add(cursor.getLong(0)); - // add secret if available (and requested) - if(exportSecret && cursor.getInt(1) != 0) - secretMasterKeyIds.add(cursor.getLong(0)); - } while(cursor.moveToNext()); - } finally { - cursor.close(); - } - - PgpImportExport pgpImportExport = new PgpImportExport(this, this, this); - Bundle resultData = pgpImportExport - .exportKeyRings(publicMasterKeyIds, secretMasterKeyIds, - new FileOutputStream(outputFile)); - - if (mIsCanceled) { - boolean isDeleted = new File(outputFile).delete(); - } - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_UPLOAD_KEYRING.equals(action)) { - try { - - /* Input */ - String keyServer = data.getString(UPLOAD_KEY_SERVER); - // and dataUri! - - /* Operation */ - HkpKeyServer server = new HkpKeyServer(keyServer); - - PGPPublicKeyRing keyring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, dataUri); - if (keyring != null) { - PgpImportExport pgpImportExport = new PgpImportExport(this, null); - - boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, - (PGPPublicKeyRing) keyring); - if (!uploaded) { - throw new PgpGeneralException("Unable to export key to selected server"); - } - } - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_DOWNLOAD_AND_IMPORT_KEYS.equals(action)) { - try { - ArrayList<ImportKeysListEntry> entries = data.getParcelableArrayList(DOWNLOAD_KEY_LIST); - String keyServer = data.getString(DOWNLOAD_KEY_SERVER); - - // this downloads the keys and places them into the ImportKeysListEntry entries - HkpKeyServer server = new HkpKeyServer(keyServer); - - for (ImportKeysListEntry entry : entries) { - // if available use complete fingerprint for get request - byte[] downloadedKeyBytes; - if (entry.getFingerPrintHex() != null) { - downloadedKeyBytes = server.get("0x" + entry.getFingerPrintHex()).getBytes(); - } else { - downloadedKeyBytes = server.get(entry.getKeyIdHex()).getBytes(); - } - - // create PGPKeyRing object based on downloaded armored key - PGPKeyRing downloadedKey = null; - BufferedInputStream bufferedInput = - new BufferedInputStream(new ByteArrayInputStream(downloadedKeyBytes)); - if (bufferedInput.available() > 0) { - InputStream in = PGPUtil.getDecoderStream(bufferedInput); - PGPObjectFactory objectFactory = new PGPObjectFactory(in); - - // get first object in block - Object obj; - if ((obj = objectFactory.nextObject()) != null) { - Log.d(Constants.TAG, "Found class: " + obj.getClass()); - - if (obj instanceof PGPKeyRing) { - downloadedKey = (PGPKeyRing) obj; - } else { - throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); - } - } - } - - // verify downloaded key by comparing fingerprints - if (entry.getFingerPrintHex() != null) { - String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex( - downloadedKey.getPublicKey().getFingerprint()); - if (downloadedKeyFp.equals(entry.getFingerPrintHex())) { - Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " + - "the requested fingerprint!"); - } else { - throw new PgpGeneralException("fingerprint of downloaded key is " + - "NOT the same as the requested fingerprint!"); - } - } - - // save key bytes in entry object for doing the - // actual import afterwards - entry.setBytes(downloadedKey.getEncoded()); - } - - - Intent importIntent = new Intent(this, KeychainIntentService.class); - importIntent.setAction(ACTION_IMPORT_KEYRING); - Bundle importData = new Bundle(); - importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); - importIntent.putExtra(EXTRA_DATA, importData); - importIntent.putExtra(EXTRA_MESSENGER, mMessenger); - - // now import it with this service - onHandleIntent(importIntent); - - // result is handled in ACTION_IMPORT_KEYRING - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_CERTIFY_KEYRING.equals(action)) { - try { - - /* Input */ - long masterKeyId = data.getLong(CERTIFY_KEY_MASTER_KEY_ID); - long pubKeyId = data.getLong(CERTIFY_KEY_PUB_KEY_ID); - ArrayList<String> userIds = data.getStringArrayList(CERTIFY_KEY_UIDS); - - /* Operation */ - String signaturePassphrase = PassphraseCacheService.getCachedPassphrase(this, - masterKeyId); - if (signaturePassphrase == null) { - throw new PgpGeneralException("Unable to obtain passphrase"); - } - - PgpKeyOperation keyOperation = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPPublicKeyRing publicRing = ProviderHelper.getPGPPublicKeyRing(this, pubKeyId); - PGPPublicKey publicKey = publicRing.getPublicKey(pubKeyId); - PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(this, - masterKeyId); - publicKey = keyOperation.certifyKey(certificationKey, publicKey, - userIds, signaturePassphrase); - publicRing = PGPPublicKeyRing.insertPublicKey(publicRing, publicKey); - - // store the signed key in our local cache - PgpImportExport pgpImportExport = new PgpImportExport(this, null); - int retval = pgpImportExport.storeKeyRingInCache(publicRing); - if (retval != Id.return_value.ok && retval != Id.return_value.updated) { - throw new PgpGeneralException("Failed to store signed key in local cache"); - } - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); - } catch (Exception e) { - sendErrorToHandler(e); - } - } - } - - private void sendErrorToHandler(Exception e) { - // Service was canceled. Do not send error to handler. - if (this.mIsCanceled) { - return; - } - // contextualize the exception, if necessary - if (e instanceof PgpGeneralMsgIdException) { - e = ((PgpGeneralMsgIdException) e).getContextualized(this); - } - Log.e(Constants.TAG, "ApgService Exception: ", e); - e.printStackTrace(); - - Bundle data = new Bundle(); - data.putString(KeychainIntentServiceHandler.DATA_ERROR, e.getMessage()); - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_EXCEPTION, null, data); - } - - private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) { - // Service was canceled. Do not send message to handler. - if (this.mIsCanceled) { - return; - } - Message msg = Message.obtain(); - msg.arg1 = arg1; - if (arg2 != null) { - msg.arg2 = arg2; - } - if (data != null) { - msg.setData(data); - } - - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } - - private void sendMessageToHandler(Integer arg1, Bundle data) { - sendMessageToHandler(arg1, null, data); - } - - private void sendMessageToHandler(Integer arg1) { - sendMessageToHandler(arg1, null, null); - } - - /** - * Set progressDialogUpdater of ProgressDialog by sending message to handler on UI thread - */ - public void setProgress(String message, int progress, int max) { - Log.d(Constants.TAG, "Send message by setProgress with progressDialogUpdater=" + progress + ", max=" - + max); - - Bundle data = new Bundle(); - if (message != null) { - data.putString(KeychainIntentServiceHandler.DATA_MESSAGE, message); - } - data.putInt(KeychainIntentServiceHandler.DATA_PROGRESS, progress); - data.putInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX, max); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS, null, data); - } - - public void setProgress(int resourceId, int progress, int max) { - setProgress(getString(resourceId), progress, max); - } - - public void setProgress(int progress, int max) { - setProgress(null, progress, max); - } - - @Override - public boolean hasServiceStopped() { - return mIsCanceled; - } -} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java deleted file mode 100644 index 92d012c80..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.service; - -import android.app.Activity; -import android.content.DialogInterface.OnCancelListener; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.widget.Toast; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; - -public class KeychainIntentServiceHandler extends Handler { - - // possible messages send from this service to handler on ui - public static final int MESSAGE_OKAY = 1; - public static final int MESSAGE_EXCEPTION = 2; - public static final int MESSAGE_UPDATE_PROGRESS = 3; - - // possible data keys for messages - public static final String DATA_ERROR = "error"; - public static final String DATA_PROGRESS = "progress"; - public static final String DATA_PROGRESS_MAX = "max"; - public static final String DATA_MESSAGE = "message"; - public static final String DATA_MESSAGE_ID = "message_id"; - - Activity mActivity; - ProgressDialogFragment mProgressDialogFragment; - - public KeychainIntentServiceHandler(Activity activity) { - this.mActivity = activity; - } - - public KeychainIntentServiceHandler(Activity activity, - ProgressDialogFragment progressDialogFragment) { - this.mActivity = activity; - this.mProgressDialogFragment = progressDialogFragment; - } - - public KeychainIntentServiceHandler(Activity activity, String progressDialogMessage, - int progressDialogStyle) { - this(activity, progressDialogMessage, progressDialogStyle, false, null); - } - - public KeychainIntentServiceHandler(Activity activity, String progressDialogMessage, - int progressDialogStyle, boolean cancelable, - OnCancelListener onCancelListener) { - this.mActivity = activity; - this.mProgressDialogFragment = ProgressDialogFragment.newInstance( - progressDialogMessage, - progressDialogStyle, - cancelable, - onCancelListener); - } - - public void showProgressDialog(FragmentActivity activity) { - // TODO: This is a hack!, see - // http://stackoverflow.com/questions/10114324/show-dialogfragment-from-onactivityresult - final FragmentManager manager = activity.getSupportFragmentManager(); - Handler handler = new Handler(); - handler.post(new Runnable() { - public void run() { - mProgressDialogFragment.show(manager, "progressDialog"); - } - }); - } - - @Override - public void handleMessage(Message message) { - Bundle data = message.getData(); - - switch (message.arg1) { - case MESSAGE_OKAY: - mProgressDialogFragment.dismissAllowingStateLoss(); - - break; - - case MESSAGE_EXCEPTION: - mProgressDialogFragment.dismissAllowingStateLoss(); - - // show error from service - if (data.containsKey(DATA_ERROR)) { - Toast.makeText(mActivity, - mActivity.getString(R.string.error_message, data.getString(DATA_ERROR)), - Toast.LENGTH_SHORT).show(); - } - - break; - - case MESSAGE_UPDATE_PROGRESS: - if (data.containsKey(DATA_PROGRESS) && data.containsKey(DATA_PROGRESS_MAX)) { - - // update progress from service - if (data.containsKey(DATA_MESSAGE)) { - mProgressDialogFragment.setProgress(data.getString(DATA_MESSAGE), - data.getInt(DATA_PROGRESS), data.getInt(DATA_PROGRESS_MAX)); - } else if (data.containsKey(DATA_MESSAGE_ID)) { - mProgressDialogFragment.setProgress(data.getInt(DATA_MESSAGE_ID), - data.getInt(DATA_PROGRESS), data.getInt(DATA_PROGRESS_MAX)); - } else { - mProgressDialogFragment.setProgress(data.getInt(DATA_PROGRESS), - data.getInt(DATA_PROGRESS_MAX)); - } - } - - break; - - default: - break; - } - } -} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java deleted file mode 100644 index 962b304c7..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.service; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.util.LongSparseArray; -import android.util.Log; - -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; - -import java.util.Date; -import java.util.Iterator; - -/** - * This service runs in its own process, but is available to all other processes as the main - * passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for - * convenience. - */ -public class PassphraseCacheService extends Service { - public static final String TAG = Constants.TAG + ": PassphraseCacheService"; - - public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX - + "PASSPHRASE_CACHE_ADD"; - public static final String ACTION_PASSPHRASE_CACHE_GET = Constants.INTENT_PREFIX - + "PASSPHRASE_CACHE_GET"; - - public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX - + "PASSPHRASE_CACHE_BROADCAST"; - - public static final String EXTRA_TTL = "ttl"; - public static final String EXTRA_KEY_ID = "key_id"; - public static final String EXTRA_PASSPHRASE = "passphrase"; - public static final String EXTRA_MESSENGER = "messenger"; - - private static final int REQUEST_ID = 0; - private static final long DEFAULT_TTL = 15; - - private BroadcastReceiver mIntentReceiver; - - private LongSparseArray<String> mPassphraseCache = new LongSparseArray<String>(); - - Context mContext; - - /** - * 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 - * new events to the alarm manager for new passphrases to let them timeout in the future. - * - * @param context - * @param keyId - * @param passphrase - */ - public static void addCachedPassphrase(Context context, long keyId, String passphrase) { - Log.d(TAG, "cacheNewPassphrase() for " + keyId); - - Intent intent = new Intent(context, PassphraseCacheService.class); - intent.setAction(ACTION_PASSPHRASE_CACHE_ADD); - intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassphraseCacheTtl()); - intent.putExtra(EXTRA_PASSPHRASE, passphrase); - intent.putExtra(EXTRA_KEY_ID, keyId); - - context.startService(intent); - } - - /** - * Gets a cached passphrase from memory by sending an intent to the service. This method is - * designed to wait until the service returns the passphrase. - * - * @param context - * @param keyId - * @return passphrase or null (if no passphrase is cached for this keyId) - */ - public static String getCachedPassphrase(Context context, long keyId) { - Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId); - - Intent intent = new Intent(context, PassphraseCacheService.class); - intent.setAction(ACTION_PASSPHRASE_CACHE_GET); - - final Object mutex = new Object(); - final Bundle returnBundle = new Bundle(); - - HandlerThread handlerThread = new HandlerThread("getPassphraseThread"); - handlerThread.start(); - Handler returnHandler = new Handler(handlerThread.getLooper()) { - @Override - public void handleMessage(Message message) { - if (message.obj != null) { - String passphrase = ((Bundle) message.obj).getString(EXTRA_PASSPHRASE); - returnBundle.putString(EXTRA_PASSPHRASE, passphrase); - } - synchronized (mutex) { - mutex.notify(); - } - // quit handlerThread - getLooper().quit(); - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - intent.putExtra(EXTRA_KEY_ID, keyId); - intent.putExtra(EXTRA_MESSENGER, messenger); - // send intent to this service - context.startService(intent); - - // Wait on mutex until passphrase is returned to handlerThread - synchronized (mutex) { - try { - mutex.wait(3000); - } catch (InterruptedException e) { - } - } - - if (returnBundle.containsKey(EXTRA_PASSPHRASE)) { - return returnBundle.getString(EXTRA_PASSPHRASE); - } else { - return null; - } - } - - /** - * Internal implementation to get cached passphrase. - * - * @param keyId - * @return - */ - private String getCachedPassphraseImpl(long keyId) { - Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId); - - // try to get master key id which is used as an identifier for cached passphrases - long masterKeyId = keyId; - if (masterKeyId != Id.key.symmetric) { - masterKeyId = ProviderHelper.getMasterKeyId(this, - KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); - // Failure - if(masterKeyId == 0) - return null; - } - Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId); - - // get cached passphrase - String cachedPassphrase = mPassphraseCache.get(masterKeyId); - if (cachedPassphrase == null) { - // if key has no passphrase -> cache and return empty passphrase - if (!hasPassphrase(this, masterKeyId)) { - Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!"); - - addCachedPassphrase(this, masterKeyId, ""); - return ""; - } else { - return null; - } - } - // set it again to reset the cache life cycle - Log.d(TAG, "Cache passphrase again when getting it!"); - addCachedPassphrase(this, masterKeyId, cachedPassphrase); - - return cachedPassphrase; - } - - /** - * Checks if key has a passphrase. - * - * @param secretKeyId - * @return true if it has a passphrase - */ - public static boolean hasPassphrase(Context context, long secretKeyId) { - // check if the key has no passphrase - try { - PGPSecretKeyRing secRing = ProviderHelper.getPGPSecretKeyRing(context, secretKeyId); - PGPSecretKey secretKey = null; - boolean foundValidKey = false; - for (Iterator keys = secRing.getSecretKeys(); keys.hasNext(); ) { - secretKey = (PGPSecretKey) keys.next(); - if (!secretKey.isPrivateKeyEmpty()) { - foundValidKey = true; - break; - } - } - - if (!foundValidKey) { - return false; - } - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - "SC").build("".toCharArray()); - PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); - if (testKey != null) { - return false; - } - } catch (PGPException e) { - // silently catch - } - - return true; - } - - /** - * Register BroadcastReceiver that is unregistered when service is destroyed. This - * BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to then timeout - * specific passphrases in memory. - */ - private void registerReceiver() { - if (mIntentReceiver == null) { - mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - - Log.d(TAG, "Received broadcast..."); - - if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) { - long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - timeout(context, keyId); - } - } - }; - - IntentFilter filter = new IntentFilter(); - filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE); - registerReceiver(mIntentReceiver, filter); - } - } - - /** - * Build pending intent that is executed by alarm manager to time out a specific passphrase - * - * @param context - * @param keyId - * @return - */ - private static PendingIntent buildIntent(Context context, long keyId) { - Intent intent = new Intent(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE); - intent.putExtra(EXTRA_KEY_ID, keyId); - PendingIntent sender = PendingIntent.getBroadcast(context, REQUEST_ID, intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - return sender; - } - - /** - * Executed when service is started by intent - */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.d(TAG, "onStartCommand()"); - - // register broadcastreceiver - registerReceiver(); - - if (intent != null && intent.getAction() != null) { - if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) { - long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL); - long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); - - Log.d(TAG, - "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: " - + keyId + ", ttl: " + ttl); - - // add keyId and passphrase to memory - mPassphraseCache.put(keyId, passphrase); - - if (ttl > 0) { - // register new alarm with keyId for this passphrase - long triggerTime = new Date().getTime() + (ttl * 1000); - AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); - am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId)); - } - } else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) { - long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER); - - String passphrase = getCachedPassphraseImpl(keyId); - - Message msg = Message.obtain(); - Bundle bundle = new Bundle(); - bundle.putString(EXTRA_PASSPHRASE, passphrase); - msg.obj = bundle; - try { - messenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "Sending message failed", e); - } - } else { - Log.e(Constants.TAG, "Intent or Intent Action not supported!"); - } - } - - return START_STICKY; - } - - /** - * Called when one specific passphrase for keyId timed out - * - * @param context - * @param keyId - */ - private void timeout(Context context, long keyId) { - // remove passphrase corresponding to keyId from memory - mPassphraseCache.remove(keyId); - - Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!"); - - // stop whole service if no cached passphrases remaining - if (mPassphraseCache.size() == 0) { - Log.d(TAG, "No passphrases remaining in memory, stopping service!"); - stopSelf(); - } - } - - @Override - public void onCreate() { - super.onCreate(); - mContext = this; - Log.d(Constants.TAG, "PassphraseCacheService, onCreate()"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - Log.d(Constants.TAG, "PassphraseCacheService, onDestroy()"); - - unregisterReceiver(mIntentReceiver); - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - public class PassphraseCacheBinder extends Binder { - public PassphraseCacheService getService() { - return PassphraseCacheService.this; - } - } - - private final IBinder mBinder = new PassphraseCacheBinder(); - -} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java deleted file mode 100644 index 7c2dcf2c1..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2014 Ash Hughes <ashes-iontach@hotmail.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -package org.sufficientlysecure.keychain.service; - -import android.os.Parcel; -import android.os.Parcelable; - -import org.spongycastle.openpgp.PGPSecretKey; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; - -import java.util.ArrayList; -import java.util.GregorianCalendar; - -public class SaveKeyringParcel implements Parcelable { - - public ArrayList<String> userIDs; - public ArrayList<String> originalIDs; - public ArrayList<String> deletedIDs; - public boolean[] newIDs; - public boolean primaryIDChanged; - public boolean[] moddedKeys; - public ArrayList<PGPSecretKey> deletedKeys; - public ArrayList<GregorianCalendar> keysExpiryDates; - public ArrayList<Integer> keysUsages; - public String newPassphrase; - public String oldPassphrase; - public boolean[] newKeys; - public ArrayList<PGPSecretKey> keys; - public String originalPrimaryID; - - public SaveKeyringParcel() {} - - private SaveKeyringParcel(Parcel source) { - userIDs = (ArrayList<String>) source.readSerializable(); - originalIDs = (ArrayList<String>) source.readSerializable(); - deletedIDs = (ArrayList<String>) source.readSerializable(); - newIDs = source.createBooleanArray(); - primaryIDChanged = source.readByte() != 0; - moddedKeys = source.createBooleanArray(); - byte[] tmp = source.createByteArray(); - if (tmp == null) { - deletedKeys = null; - } else { - deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp); - } - keysExpiryDates = (ArrayList<GregorianCalendar>) source.readSerializable(); - keysUsages = source.readArrayList(Integer.class.getClassLoader()); - newPassphrase = source.readString(); - oldPassphrase = source.readString(); - newKeys = source.createBooleanArray(); - keys = PgpConversionHelper.BytesToPGPSecretKeyList(source.createByteArray()); - originalPrimaryID = source.readString(); - } - - @Override - public void writeToParcel(Parcel destination, int flags) { - destination.writeSerializable(userIDs); //might not be the best method to store. - destination.writeSerializable(originalIDs); - destination.writeSerializable(deletedIDs); - destination.writeBooleanArray(newIDs); - destination.writeByte((byte) (primaryIDChanged ? 1 : 0)); - destination.writeBooleanArray(moddedKeys); - byte[] tmp = null; - if (deletedKeys.size() != 0) { - tmp = PgpConversionHelper.PGPSecretKeyArrayListToBytes(deletedKeys); - } - destination.writeByteArray(tmp); - destination.writeSerializable(keysExpiryDates); - destination.writeList(keysUsages); - destination.writeString(newPassphrase); - destination.writeString(oldPassphrase); - destination.writeBooleanArray(newKeys); - destination.writeByteArray(PgpConversionHelper.PGPSecretKeyArrayListToBytes(keys)); - destination.writeString(originalPrimaryID); - } - - public static final Creator<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() { - public SaveKeyringParcel createFromParcel(final Parcel source) { - return new SaveKeyringParcel(source); - } - - public SaveKeyringParcel[] newArray(final int size) { - return new SaveKeyringParcel[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } -} |