diff options
Diffstat (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service')
19 files changed, 0 insertions, 3543 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java deleted file mode 100644 index ba3169b18..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ /dev/null @@ -1,869 +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 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; - -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -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.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpImportExport; -import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; -import org.sufficientlysecure.keychain.pgp.PgpOperation; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream; -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.KeyServer.KeyInfo; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; - -import android.app.IntentService; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; - -/** - * 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 { - - /* 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_QUERY_KEYRING = Constants.INTENT_PREFIX + "QUERY_KEYRING"; - - public static final String ACTION_SIGN_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_FILE = 2; - public static final int TARGET_STREAM = 3; - - // encrypt - public static final String ENCRYPT_SECRET_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_GENERATE_SIGNATURE = "generate_signature"; - public static final String ENCRYPT_SIGN_ONLY = "sign_only"; - 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_PROVIDER_URI = "provider_uri"; - - // decrypt/verify - public static final String DECRYPT_SIGNED_ONLY = "signed_only"; - public static final String DECRYPT_RETURN_BYTES = "return_binary"; - public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; - public static final String DECRYPT_ASSUME_SYMMETRIC = "assume_symmetric"; - public static final String DECRYPT_LOOKUP_UNKNOWN_KEY = "lookup_unknownKey"; - - // save keyring - public static final String SAVE_KEYRING_NEW_PASSPHRASE = "new_passphrase"; - public static final String SAVE_KEYRING_CURRENT_PASSPHRASE = "current_passphrase"; - public static final String SAVE_KEYRING_USER_IDS = "user_ids"; - public static final String SAVE_KEYRING_KEYS = "keys"; - public static final String SAVE_KEYRING_KEYS_USAGES = "keys_usages"; - public static final String SAVE_KEYRING_MASTER_KEY_ID = "master_key_id"; - 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_INPUT_STREAM = "import_input_stream"; - public static final String IMPORT_FILENAME = "import_filename"; - public static final String IMPORT_BYTES = "import_bytes"; - 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_KEY_TYPE = "export_key_type"; - 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"; - public static final String UPLOAD_KEY_KEYRING_ROW_ID = "upload_key_ring_id"; - - // query key - public static final String QUERY_KEY_SERVER = "query_key_server"; - public static final String QUERY_KEY_TYPE = "query_key_type"; - public static final String QUERY_KEY_STRING = "query_key_string"; - public static final String QUERY_KEY_ID = "query_key_id"; - - // sign key - public static final String SIGN_KEY_MASTER_KEY_ID = "sign_key_master_key_id"; - public static final String SIGN_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; - - /* - * possible data keys as result send over messenger - */ - // keys - public static final String RESULT_NEW_KEY = "new_key"; - public static final String RESULT_NEW_KEY2 = "new_key2"; - - // encrypt - public static final String RESULT_SIGNATURE_BYTES = "signature_data"; - public static final String RESULT_SIGNATURE_STRING = "signature_text"; - public static final String RESULT_ENCRYPTED_STRING = "encrypted_message"; - public static final String RESULT_ENCRYPTED_BYTES = "encrypted_data"; - public static final String RESULT_URI = "result_uri"; - - // decrypt/verify - public static final String RESULT_DECRYPTED_STRING = "decrypted_message"; - public static final String RESULT_DECRYPTED_BYTES = "decrypted_data"; - public static final String RESULT_SIGNATURE = "signature"; - public static final String RESULT_SIGNATURE_KEY_ID = "signature_key_id"; - public static final String RESULT_SIGNATURE_USER_ID = "signature_user_id"; - - public static final String RESULT_SIGNATURE_SUCCESS = "signature_success"; - public static final String RESULT_SIGNATURE_UNKNOWN = "signature_unknown"; - public static final String RESULT_SIGNATURE_LOOKUP_KEY = "lookup_key"; - - // 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"; - - // query - public static final String RESULT_QUERY_KEY_DATA = "query_key_data"; - public static final String RESULT_QUERY_KEY_SEARCH_RESULT = "query_key_search_result"; - - Messenger mMessenger; - - public KeychainIntentService() { - super("ApgService"); - } - - /** - * 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; - } - - mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); - Bundle data = extras.getBundle(EXTRA_DATA); - - OtherHelper.logDebugBundle(data, "EXTRA_DATA"); - - String action = intent.getAction(); - - // execute action from extra bundle - if (ACTION_ENCRYPT_SIGN.equals(action)) { - try { - /* Input */ - int target = data.getInt(TARGET); - - long secretKeyId = data.getLong(ENCRYPT_SECRET_KEY_ID); - String encryptionPassphrase = data.getString(GENERATE_KEY_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); - boolean generateSignature = data.getBoolean(ENCRYPT_GENERATE_SIGNATURE); - boolean signOnly = data.getBoolean(ENCRYPT_SIGN_ONLY); - - InputStream inStream = null; - long inLength = -1; - InputData inputData = null; - OutputStream outStream = null; - 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_FILE: /* 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; - - 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 */ - PgpOperation operation = new PgpOperation(this, this, inputData, outStream); - if (generateSignature) { - Log.d(Constants.TAG, "generating signature..."); - operation.generateSignature(useAsciiArmor, false, secretKeyId, - PassphraseCacheService.getCachedPassphrase(this, secretKeyId), - Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences - .getPreferences(this).getForceV3Signatures()); - } else if (signOnly) { - Log.d(Constants.TAG, "sign only..."); - operation.signText(secretKeyId, PassphraseCacheService.getCachedPassphrase( - this, secretKeyId), Preferences.getPreferences(this) - .getDefaultHashAlgorithm(), Preferences.getPreferences(this) - .getForceV3Signatures()); - } else { - Log.d(Constants.TAG, "encrypt..."); - operation.signAndEncrypt(useAsciiArmor, compressionId, encryptionKeyIds, - encryptionPassphrase, Preferences.getPreferences(this) - .getDefaultEncryptionAlgorithm(), secretKeyId, Preferences - .getPreferences(this).getDefaultHashAlgorithm(), Preferences - .getPreferences(this).getForceV3Signatures(), - PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); - } - - outStream.close(); - - /* Output */ - - Bundle resultData = new Bundle(); - - switch (target) { - case TARGET_BYTES: - if (useAsciiArmor) { - String output = new String( - ((ByteArrayOutputStream) outStream).toByteArray()); - if (generateSignature) { - resultData.putString(RESULT_SIGNATURE_STRING, output); - } else { - resultData.putString(RESULT_ENCRYPTED_STRING, output); - } - } else { - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - if (generateSignature) { - resultData.putByteArray(RESULT_SIGNATURE_BYTES, output); - } else { - resultData.putByteArray(RESULT_ENCRYPTED_BYTES, output); - } - } - - break; - case TARGET_FILE: - // 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); - - long secretKeyId = data.getLong(ENCRYPT_SECRET_KEY_ID); - byte[] bytes = data.getByteArray(DECRYPT_CIPHERTEXT_BYTES); - boolean signedOnly = data.getBoolean(DECRYPT_SIGNED_ONLY); - boolean returnBytes = data.getBoolean(DECRYPT_RETURN_BYTES); - boolean assumeSymmetricEncryption = data.getBoolean(DECRYPT_ASSUME_SYMMETRIC); - - boolean lookupUnknownKey = data.getBoolean(DECRYPT_LOOKUP_UNKNOWN_KEY); - - InputStream inStream = null; - long inLength = -1; - InputData inputData = null; - OutputStream outStream = null; - 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_FILE: /* 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; - - 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 - PgpOperation operation = new PgpOperation(this, this, inputData, outStream); - if (signedOnly) { - resultData = operation.verifyText(lookupUnknownKey); - } else { - resultData = operation.decryptAndVerify( - PassphraseCacheService.getCachedPassphrase(this, secretKeyId), - assumeSymmetricEncryption); - } - - outStream.close(); - - /* Output */ - - switch (target) { - case TARGET_BYTES: - if (returnBytes) { - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - resultData.putByteArray(RESULT_DECRYPTED_BYTES, output); - } else { - String output = new String( - ((ByteArrayOutputStream) outStream).toByteArray()); - resultData.putString(RESULT_DECRYPTED_STRING, output); - } - - break; - case TARGET_FILE: - // 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 */ - String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE); - String newPassPhrase = data.getString(SAVE_KEYRING_NEW_PASSPHRASE); - boolean canSign = true; - - if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) { - canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN); - } - - if (newPassPhrase == null) { - newPassPhrase = oldPassPhrase; - } - ArrayList<String> userIds = data.getStringArrayList(SAVE_KEYRING_USER_IDS); - ArrayList<PGPSecretKey> keys = PgpConversionHelper.BytesToPGPSecretKeyList(data - .getByteArray(SAVE_KEYRING_KEYS)); - ArrayList<Integer> keysUsages = data.getIntegerArrayList(SAVE_KEYRING_KEYS_USAGES); - long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID); - - PgpKeyOperation keyOperations = new PgpKeyOperation(this, this); - /* Operation */ - if (!canSign) { - keyOperations.changeSecretKeyPassphrase( - ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId), - oldPassPhrase, newPassPhrase); - } else { - keyOperations.buildSecretKey(userIds, keys, keysUsages, masterKeyId, - oldPassPhrase, newPassPhrase); - } - 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); - PGPSecretKey masterKey = null; - if (data.containsKey(GENERATE_KEY_MASTER_KEY)) { - masterKey = PgpConversionHelper.BytesToPGPSecretKey(data - .getByteArray(GENERATE_KEY_MASTER_KEY)); - } - - /* Operation */ - PgpKeyOperation keyOperations = new PgpKeyOperation(this, this); - PGPSecretKeyRing newKeyRing = keyOperations.createKey(algorithm, keysize, - passphrase, masterKey); - - /* Output */ - Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyRingToBytes(newKeyRing)); - - 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); - - /* Operation */ - PgpKeyOperation keyOperations = new PgpKeyOperation(this, this); - - PGPSecretKeyRing masterKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa, - 4096, passphrase, null); - - PGPSecretKeyRing subKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa, - 4096, passphrase, masterKeyRing.getSecretKey()); - - /* Output */ - Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyRingToBytes(masterKeyRing)); - resultData.putByteArray(RESULT_NEW_KEY2, - PgpConversionHelper.PGPSecretKeyRingToBytes(subKeyRing)); - - 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 { - - /* Input */ - int target = data.getInt(TARGET); - - /* Operation */ - InputStream inStream = null; - long inLength = -1; - InputData inputData = null; - switch (target) { - case TARGET_BYTES: /* import key from bytes directly */ - byte[] bytes = data.getByteArray(IMPORT_BYTES); - - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; - - inputData = new InputData(inStream, inLength); - - break; - case TARGET_FILE: /* import key from file */ - String inputFile = data.getString(IMPORT_FILENAME); - - inStream = new FileInputStream(inputFile); - File file = new File(inputFile); - inLength = file.length(); - inputData = new InputData(inStream, inLength); - - break; - - case TARGET_STREAM: - // TODO: not implemented - break; - } - - Bundle resultData = new Bundle(); - - ArrayList<Long> keyIds = (ArrayList<Long>) data.getSerializable(IMPORT_KEY_LIST); - - PgpImportExport pgpImportExport = new PgpImportExport(this, this); - resultData = pgpImportExport.importKeyRings(inputData, keyIds); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_EXPORT_KEYRING.equals(action)) { - try { - - /* Input */ - int keyType = Id.type.public_key; - if (data.containsKey(EXPORT_KEY_TYPE)) { - keyType = data.getInt(EXPORT_KEY_TYPE); - } - - String outputFile = data.getString(EXPORT_FILENAME); - - boolean exportAll = data.getBoolean(EXPORT_ALL); - long keyRingMasterKeyId = -1; - if (!exportAll) { - keyRingMasterKeyId = data.getLong(EXPORT_KEY_RING_MASTER_KEY_ID); - } - - /* Operation */ - - // check if storage is ready - if (!FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready)); - } - - // OutputStream - FileOutputStream outStream = new FileOutputStream(outputFile); - - ArrayList<Long> keyRingMasterKeyIds = new ArrayList<Long>(); - if (exportAll) { - // get all key ring row ids based on export type - - if (keyType == Id.type.public_key) { - keyRingMasterKeyIds = ProviderHelper.getPublicKeyRingsMasterKeyIds(this); - } else { - keyRingMasterKeyIds = ProviderHelper.getSecretKeyRingsMasterKeyIds(this); - } - } else { - keyRingMasterKeyIds.add(keyRingMasterKeyId); - } - - Bundle resultData = new Bundle(); - - PgpImportExport pgpImportExport = new PgpImportExport(this, this); - resultData = pgpImportExport - .exportKeyRings(keyRingMasterKeyIds, keyType, outStream); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_UPLOAD_KEYRING.equals(action)) { - try { - - /* Input */ - int keyRingRowId = data.getInt(UPLOAD_KEY_KEYRING_ROW_ID); - String keyServer = data.getString(UPLOAD_KEY_SERVER); - - /* Operation */ - HkpKeyServer server = new HkpKeyServer(keyServer); - - PGPPublicKeyRing keyring = ProviderHelper.getPGPPublicKeyRingByRowId(this, - keyRingRowId); - 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_QUERY_KEYRING.equals(action)) { - try { - - /* Input */ - int queryType = data.getInt(QUERY_KEY_TYPE); - String keyServer = data.getString(QUERY_KEY_SERVER); - - String queryString = data.getString(QUERY_KEY_STRING); - long keyId = data.getLong(QUERY_KEY_ID); - - /* Operation */ - Bundle resultData = new Bundle(); - - HkpKeyServer server = new HkpKeyServer(keyServer); - if (queryType == Id.keyserver.search) { - ArrayList<KeyInfo> searchResult = server.search(queryString); - - resultData.putParcelableArrayList(RESULT_QUERY_KEY_SEARCH_RESULT, searchResult); - } else if (queryType == Id.keyserver.get) { - String keyData = server.get(keyId); - - resultData.putString(RESULT_QUERY_KEY_DATA, keyData); - } - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - } else if (ACTION_SIGN_KEYRING.equals(action)) { - try { - - /* Input */ - long masterKeyId = data.getLong(SIGN_KEY_MASTER_KEY_ID); - long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID); - - /* Operation */ - String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this, - masterKeyId); - - PgpKeyOperation keyOperation = new PgpKeyOperation(this, this); - PGPPublicKeyRing signedPubKeyRing = keyOperation.signKey(masterKeyId, pubKeyId, - signaturePassPhrase); - - // store the signed key in our local cache - PgpImportExport pgpImportExport = new PgpImportExport(this, null); - int retval = pgpImportExport.storeKeyRingInCache(signedPubKeyRing); - 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) { - 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) { - 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 progress 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 progress=" + 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); - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java deleted file mode 100644 index 170b946d2..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ /dev/null @@ -1,110 +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 org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; -import org.sufficientlysecure.keychain.R; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.support.v4.app.FragmentActivity; -import android.widget.Toast; - -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, int progressDialogMessageId, int progressDialogStyle) { - this.mActivity = activity; - this.mProgressDialogFragment = ProgressDialogFragment.newInstance(progressDialogMessageId, - progressDialogStyle); - } - - public void showProgressDialog(FragmentActivity activity) { - mProgressDialogFragment.show(activity.getSupportFragmentManager(), "progressDialog"); - } - - @Override - public void handleMessage(Message message) { - Bundle data = message.getData(); - - switch (message.arg1) { - case MESSAGE_OKAY: - mProgressDialogFragment.dismiss(); - - break; - - case MESSAGE_EXCEPTION: - mProgressDialogFragment.dismiss(); - - // 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/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java deleted file mode 100644 index 08b9c26e6..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ /dev/null @@ -1,370 +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 java.util.Date; -import java.util.HashMap; - -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.ProviderHelper; - -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.util.Log; - -/** - * 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 HashMap<Long, String> mPassphraseCache = new HashMap<Long, 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) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(this, keyId); - if (keyRing == null) { - return null; - } - PGPSecretKey masterKey = PgpKeyHelper.getMasterKey(keyRing); - if (masterKey == null) { - return null; - } - masterKeyId = masterKey.getKeyID(); - } - 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 { - PGPSecretKey secretKey = PgpKeyHelper.getMasterKey(ProviderHelper - .getPGPSecretKeyRingByKeyId(context, secretKeyId)); - 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.isEmpty()) { - 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/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java deleted file mode 100644 index 555303238..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/NoUserIdsException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sufficientlysecure.keychain.service.exception; - -public class NoUserIdsException extends Exception { - - private static final long serialVersionUID = 7009311527126696207L; - - public NoUserIdsException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java deleted file mode 100644 index 1152d6796..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/UserInteractionRequiredException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sufficientlysecure.keychain.service.exception; - -public class UserInteractionRequiredException extends Exception { - - private static final long serialVersionUID = -60128148603511936L; - - public UserInteractionRequiredException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java deleted file mode 100644 index cef002265..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPackageSignatureException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sufficientlysecure.keychain.service.exception; - -public class WrongPackageSignatureException extends Exception { - - private static final long serialVersionUID = -8294642703122196028L; - - public WrongPackageSignatureException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java deleted file mode 100644 index 14b774eb5..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/exception/WrongPassphraseException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sufficientlysecure.keychain.service.exception; - -public class WrongPassphraseException extends Exception { - - private static final long serialVersionUID = -5309689232853485740L; - - public WrongPassphraseException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java deleted file mode 100644 index 9da4c8392..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettings.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.openpgp.PGPEncryptedData; -import org.sufficientlysecure.keychain.Id; - -public class AppSettings { - private String packageName; - private byte[] packageSignature; - private long keyId = Id.key.none; - private int encryptionAlgorithm; - private int hashAlgorithm; - private int compression; - - public AppSettings() { - - } - - public AppSettings(String packageName, byte[] packageSignature) { - super(); - this.packageName = packageName; - this.packageSignature = packageSignature; - // defaults: - this.encryptionAlgorithm = PGPEncryptedData.AES_256; - this.hashAlgorithm = HashAlgorithmTags.SHA512; - this.compression = Id.choice.compression.zlib; - } - - public String getPackageName() { - return packageName; - } - - public void setPackageName(String packageName) { - this.packageName = packageName; - } - - public byte[] getPackageSignature() { - return packageSignature; - } - - public void setPackageSignature(byte[] packageSignature) { - this.packageSignature = packageSignature; - } - - public long getKeyId() { - return keyId; - } - - public void setKeyId(long scretKeyId) { - this.keyId = scretKeyId; - } - - public int getEncryptionAlgorithm() { - return encryptionAlgorithm; - } - - public void setEncryptionAlgorithm(int encryptionAlgorithm) { - this.encryptionAlgorithm = encryptionAlgorithm; - } - - public int getHashAlgorithm() { - return hashAlgorithm; - } - - public void setHashAlgorithm(int hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm; - } - - public int getCompression() { - return compression; - } - - public void setCompression(int compression) { - this.compression = compression; - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java deleted file mode 100644 index 8d56fc593..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsActivity.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.View; - -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; - -public class AppSettingsActivity extends SherlockFragmentActivity { - private Uri mAppUri; - - private AppSettingsFragment mSettingsFragment; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Inflate a "Done" custom action bar - ActionBarHelper.setDoneView(getSupportActionBar(), R.string.api_settings_save, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // "Done" - save(); - } - }); - - setContentView(R.layout.api_app_settings_activity); - - mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( - R.id.api_app_settings_fragment); - - Intent intent = getIntent(); - mAppUri = intent.getData(); - if (mAppUri == null) { - Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); - finish(); - return; - } else { - Log.d(Constants.TAG, "uri: " + mAppUri); - loadData(mAppUri); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getSupportMenuInflater().inflate(R.menu.api_app_settings, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_api_settings_revoke: - revokeAccess(); - return true; - case R.id.menu_api_settings_cancel: - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - private void loadData(Uri appUri) { - AppSettings settings = ProviderHelper.getApiAppSettings(this, appUri); - mSettingsFragment.setAppSettings(settings); - } - - private void revokeAccess() { - if (getContentResolver().delete(mAppUri, null, null) <= 0) { - throw new RuntimeException(); - } - finish(); - } - - private void save() { - ProviderHelper.updateApiApp(this, mSettingsFragment.getAppSettings(), mAppUri); - - finish(); - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java deleted file mode 100644 index 025929cfa..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2013-2014 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.remote; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.spongycastle.util.encoders.Hex; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment; -import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter; -import org.sufficientlysecure.keychain.util.AlgorithmNames; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; - -import com.beardedhen.androidbootstrap.BootstrapButton; - -public class AppSettingsFragment extends Fragment implements - SelectSecretKeyLayoutFragment.SelectSecretKeyCallback { - - // model - private AppSettings appSettings; - - // view - private LinearLayout mAdvancedSettingsContainer; - private BootstrapButton mAdvancedSettingsButton; - private TextView mAppNameView; - private ImageView mAppIconView; - private Spinner mEncryptionAlgorithm; - private Spinner mHashAlgorithm; - private Spinner mCompression; - private TextView mPackageName; - private TextView mPackageSignature; - - private SelectSecretKeyLayoutFragment mSelectKeyFragment; - - KeyValueSpinnerAdapter encryptionAdapter; - KeyValueSpinnerAdapter hashAdapter; - KeyValueSpinnerAdapter compressionAdapter; - - public AppSettings getAppSettings() { - return appSettings; - } - - public void setAppSettings(AppSettings appSettings) { - this.appSettings = appSettings; - setPackage(appSettings.getPackageName()); - mPackageName.setText(appSettings.getPackageName()); - - try { - MessageDigest md = MessageDigest.getInstance("SHA-256"); - md.update(appSettings.getPackageSignature()); - byte[] digest = md.digest(); - String signature = new String(Hex.encode(digest)); - - mPackageSignature.setText(signature); - } catch (NoSuchAlgorithmException e) { - Log.e(Constants.TAG, "Should not happen!", e); - } - - mSelectKeyFragment.selectKey(appSettings.getKeyId()); - mEncryptionAlgorithm.setSelection(encryptionAdapter.getPosition(appSettings - .getEncryptionAlgorithm())); - mHashAlgorithm.setSelection(hashAdapter.getPosition(appSettings.getHashAlgorithm())); - mCompression.setSelection(compressionAdapter.getPosition(appSettings.getCompression())); - } - - /** - * Inflate the layout for this fragment - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.api_app_settings_fragment, container, false); - initView(view); - return view; - } - - private void initView(View view) { - mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getFragmentManager().findFragmentById( - R.id.api_app_settings_select_key_fragment); - mSelectKeyFragment.setCallback(this); - - mAdvancedSettingsButton = (BootstrapButton) view - .findViewById(R.id.api_app_settings_advanced_button); - mAdvancedSettingsContainer = (LinearLayout) view - .findViewById(R.id.api_app_settings_advanced); - - mAppNameView = (TextView) view.findViewById(R.id.api_app_settings_app_name); - mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon); - mEncryptionAlgorithm = (Spinner) view - .findViewById(R.id.api_app_settings_encryption_algorithm); - mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm); - mCompression = (Spinner) view.findViewById(R.id.api_app_settings_compression); - mPackageName = (TextView) view.findViewById(R.id.api_app_settings_package_name); - mPackageSignature = (TextView) view.findViewById(R.id.api_app_settings_package_signature); - - AlgorithmNames algorithmNames = new AlgorithmNames(getActivity()); - - encryptionAdapter = new KeyValueSpinnerAdapter(getActivity(), - algorithmNames.getEncryptionNames()); - mEncryptionAlgorithm.setAdapter(encryptionAdapter); - mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - appSettings.setEncryptionAlgorithm((int) id); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - } - }); - - hashAdapter = new KeyValueSpinnerAdapter(getActivity(), algorithmNames.getHashNames()); - mHashAlgorithm.setAdapter(hashAdapter); - mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - appSettings.setHashAlgorithm((int) id); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - } - }); - - compressionAdapter = new KeyValueSpinnerAdapter(getActivity(), - algorithmNames.getCompressionNames()); - mCompression.setAdapter(compressionAdapter); - mCompression.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - appSettings.setCompression((int) id); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - } - }); - - final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f); - visibleAnimation.setDuration(250); - final Animation invisibleAnimation = new AlphaAnimation(1.0f, 0.0f); - invisibleAnimation.setDuration(250); - - // TODO: Better: collapse/expand animation - // final Animation animation2 = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, - // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, - // Animation.RELATIVE_TO_SELF, 0.0f); - // animation2.setDuration(150); - - mAdvancedSettingsButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (mAdvancedSettingsContainer.getVisibility() == View.VISIBLE) { - mAdvancedSettingsContainer.startAnimation(invisibleAnimation); - mAdvancedSettingsContainer.setVisibility(View.GONE); - mAdvancedSettingsButton.setText(getString(R.string.api_settings_show_advanced)); - mAdvancedSettingsButton.setLeftIcon("fa-caret-up"); - } else { - mAdvancedSettingsContainer.startAnimation(visibleAnimation); - mAdvancedSettingsContainer.setVisibility(View.VISIBLE); - mAdvancedSettingsButton.setText(getString(R.string.api_settings_hide_advanced)); - mAdvancedSettingsButton.setLeftIcon("fa-caret-down"); - } - } - }); - } - - private void setPackage(String packageName) { - PackageManager pm = getActivity().getApplicationContext().getPackageManager(); - - // get application name and icon from package manager - String appName = null; - Drawable appIcon = null; - try { - ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - - appName = (String) pm.getApplicationLabel(ai); - appIcon = pm.getApplicationIcon(ai); - } catch (final NameNotFoundException e) { - // fallback - appName = packageName; - } - mAppNameView.setText(appName); - mAppIconView.setImageDrawable(appIcon); - } - - /** - * callback from select secret key fragment - */ - @Override - public void onKeySelected(long secretKeyId) { - appSettings.setKeyId(secretKeyId); - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java deleted file mode 100644 index 427e6bb8f..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.security.cert.X509Certificate; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.PasswordCallback; - -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openssl.PEMWriter; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.pgp.PgpToX509; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.Intent; -import android.os.IBinder; -import android.os.RemoteException; - -public class ExtendedApiService extends RemoteService { - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - private void selfSignedX509CertSafe(String subjAltNameURI, IExtendedApiCallback callback, - AppSettings appSettings) { - - // TODO: for pgp keyrings with password - CallbackHandler pgpPwdCallbackHandler = new PgpToX509.PredefinedPasswordCallbackHandler(""); - - try { - long keyId = appSettings.getKeyId(); - PGPSecretKey pgpSecretKey = PgpKeyHelper.getSigningKey(this, keyId); - - PasswordCallback pgpSecKeyPasswordCallBack = new PasswordCallback("pgp passphrase?", - false); - pgpPwdCallbackHandler.handle(new Callback[] { pgpSecKeyPasswordCallBack }); - PGPPrivateKey pgpPrivKey = pgpSecretKey.extractPrivateKey( - pgpSecKeyPasswordCallBack.getPassword(), Constants.BOUNCY_CASTLE_PROVIDER_NAME); - pgpSecKeyPasswordCallBack.clearPassword(); - - X509Certificate selfSignedCert = PgpToX509.createSelfSignedCert(pgpSecretKey, - pgpPrivKey, subjAltNameURI); - - // Write x509cert and privKey into files - // FileOutputStream fosCert = context.openFileOutput(CERT_FILENAME, - // Context.MODE_PRIVATE); - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - PEMWriter pemWriterCert = new PEMWriter(new PrintWriter(outStream)); - pemWriterCert.writeObject(selfSignedCert); - pemWriterCert.close(); - - byte[] outputBytes = outStream.toByteArray(); - - callback.onSuccess(outputBytes); - } catch (Exception e) { - Log.e(Constants.TAG, "ExtendedApiService", e); - try { - callback.onError(e.getMessage()); - } catch (RemoteException e1) { - Log.e(Constants.TAG, "ExtendedApiService", e); - } - } - - // TODO: no private key at the moment! Don't give it to others - // PrivateKey privKey = pgpPrivKey.getKey(); - // FileOutputStream fosKey = context.openFileOutput(PRIV_KEY_FILENAME, - // Context.MODE_PRIVATE); - // PEMWriter pemWriterKey = new PEMWriter(new PrintWriter(fosKey)); - // pemWriterKey.writeObject(privKey); - // pemWriterKey.close(); - } - - private final IExtendedApiService.Stub mBinder = new IExtendedApiService.Stub() { - - @Override - public void encrypt(byte[] inputBytes, String passphrase, IExtendedApiCallback callback) - throws RemoteException { - // TODO : implement - - } - - @Override - public void selfSignedX509Cert(final String subjAltNameURI, - final IExtendedApiCallback callback) throws RemoteException { - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - selfSignedX509CertSafe(subjAltNameURI, callback, settings); - } - }; - - checkAndEnqueue(r); - } - - }; - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl deleted file mode 100644 index f69f66fd7..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiCallback.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.service.remote; - -interface IExtendedApiCallback { - - oneway void onSuccess(in byte[] outputBytes); - - oneway void onError(in String error); -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl deleted file mode 100644 index 669bd31b5..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/IExtendedApiService.aidl +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.service.remote; - -import org.sufficientlysecure.keychain.service.remote.IExtendedApiCallback; - -/** - * All methods are oneway, which means they are asynchronous and non-blocking. - * Results are returned to the callback, which has to be implemented on client side. - */ -interface IExtendedApiService { - - /** - * Symmetric Encrypt - * - * @param inputBytes - * Byte array you want to encrypt - * @param passphrase - * symmetric passhprase - * @param callback - * Callback where to return results - */ - oneway void encrypt(in byte[] inputBytes, in String passphrase, in IExtendedApiCallback callback); - - /** - * Generates self signed X509 certificate signed by OpenPGP private key (from app settings) - * - * @param subjAltNameURI - * @param callback - * Callback where to return results - */ - oneway void selfSignedX509Cert(in String subjAltNameURI, in IExtendedApiCallback callback); - -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java deleted file mode 100644 index 575f76a22..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.regex.Matcher; - -import org.openintents.openpgp.IOpenPgpCallback; -import org.openintents.openpgp.IOpenPgpKeyIdsCallback; -import org.openintents.openpgp.IOpenPgpService; -import org.openintents.openpgp.OpenPgpData; -import org.openintents.openpgp.OpenPgpError; -import org.openintents.openpgp.OpenPgpSignatureResult; -import org.spongycastle.util.Arrays; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpOperation; -import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.service.exception.NoUserIdsException; -import org.sufficientlysecure.keychain.service.exception.UserInteractionRequiredException; -import org.sufficientlysecure.keychain.service.exception.WrongPassphraseException; -import org.sufficientlysecure.keychain.util.InputData; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Message; -import android.os.RemoteException; - -public class OpenPgpService extends RemoteService { - - private String getCachedPassphrase(long keyId, boolean allowUserInteraction) - throws UserInteractionRequiredException { - String passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId); - - if (passphrase == null) { - if (!allowUserInteraction) { - throw new UserInteractionRequiredException( - "Passphrase not found in cache, please enter your passphrase!"); - } - - Log.d(Constants.TAG, "No passphrase! Activity required!"); - - // start passphrase dialog - PassphraseActivityCallback callback = new PassphraseActivityCallback(); - Bundle extras = new Bundle(); - extras.putLong(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId); - pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE, callback, - extras); - - if (callback.isSuccess()) { - Log.d(Constants.TAG, "New passphrase entered!"); - - // get again after it was entered - passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), keyId); - } else { - Log.d(Constants.TAG, "Passphrase dialog canceled!"); - - return null; - } - - } - - return passphrase; - } - - public class PassphraseActivityCallback extends UserInputCallback { - - private boolean success = false; - - public boolean isSuccess() { - return success; - } - - @Override - public void handleUserInput(Message msg) { - if (msg.arg1 == OKAY) { - success = true; - } else { - success = false; - } - } - }; - - /** - * Search database for key ids based on emails. - * - * @param encryptionUserIds - * @return - */ - private long[] getKeyIdsFromEmails(String[] encryptionUserIds, boolean allowUserInteraction) - throws UserInteractionRequiredException { - // find key ids to given emails in database - ArrayList<Long> keyIds = new ArrayList<Long>(); - - boolean missingUserIdsCheck = false; - boolean dublicateUserIdsCheck = false; - ArrayList<String> missingUserIds = new ArrayList<String>(); - ArrayList<String> dublicateUserIds = new ArrayList<String>(); - - for (String email : encryptionUserIds) { - Uri uri = KeychainContract.KeyRings.buildPublicKeyRingsByEmailsUri(email); - Cursor cur = getContentResolver().query(uri, null, null, null, null); - if (cur.moveToFirst()) { - long id = cur.getLong(cur.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID)); - keyIds.add(id); - } else { - missingUserIdsCheck = true; - missingUserIds.add(email); - Log.d(Constants.TAG, "user id missing"); - } - if (cur.moveToNext()) { - dublicateUserIdsCheck = true; - dublicateUserIds.add(email); - Log.d(Constants.TAG, "more than one user id with the same email"); - } - } - - // convert to long[] - long[] keyIdsArray = new long[keyIds.size()]; - for (int i = 0; i < keyIdsArray.length; i++) { - keyIdsArray[i] = keyIds.get(i); - } - - // allow the user to verify pub key selection - if (allowUserInteraction && (missingUserIdsCheck || dublicateUserIdsCheck)) { - SelectPubKeysActivityCallback callback = new SelectPubKeysActivityCallback(); - - Bundle extras = new Bundle(); - extras.putLongArray(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); - extras.putStringArrayList(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); - extras.putStringArrayList(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, - dublicateUserIds); - - pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS, callback, - extras); - - if (callback.isSuccess()) { - Log.d(Constants.TAG, "New selection of pub keys!"); - keyIdsArray = callback.getPubKeyIds(); - } else { - Log.d(Constants.TAG, "Pub key selection canceled!"); - return null; - } - } - - // if no user interaction is allow throw exceptions on duplicate or missing pub keys - if (!allowUserInteraction) { - if (missingUserIdsCheck) - throw new UserInteractionRequiredException( - "Pub keys for these user ids are missing:" + missingUserIds.toString()); - if (dublicateUserIdsCheck) - throw new UserInteractionRequiredException( - "More than one pub key with these user ids exist:" - + dublicateUserIds.toString()); - } - - if (keyIdsArray.length == 0) { - return null; - } - return keyIdsArray; - } - - public class SelectPubKeysActivityCallback extends UserInputCallback { - public static final String PUB_KEY_IDS = "pub_key_ids"; - - private boolean success = false; - private long[] pubKeyIds; - - public boolean isSuccess() { - return success; - } - - public long[] getPubKeyIds() { - return pubKeyIds; - } - - @Override - public void handleUserInput(Message msg) { - if (msg.arg1 == OKAY) { - success = true; - pubKeyIds = msg.getData().getLongArray(PUB_KEY_IDS); - } else { - success = false; - } - } - }; - - private synchronized void getKeyIdsSafe(String[] userIds, boolean allowUserInteraction, - IOpenPgpKeyIdsCallback callback, AppSettings appSettings) { - try { - long[] keyIds = getKeyIdsFromEmails(userIds, allowUserInteraction); - if (keyIds == null) { - throw new NoUserIdsException("No user ids!"); - } - - callback.onSuccess(keyIds); - } catch (UserInteractionRequiredException e) { - callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage()); - } catch (NoUserIdsException e) { - callbackOpenPgpError(callback, OpenPgpError.NO_USER_IDS, e.getMessage()); - } catch (Exception e) { - callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage()); - } - } - - private synchronized void encryptAndSignSafe(OpenPgpData inputData, - final OpenPgpData outputData, long[] keyIds, boolean allowUserInteraction, - IOpenPgpCallback callback, AppSettings appSettings, boolean sign) { - try { - // TODO: other options of OpenPgpData! - byte[] inputBytes = getInput(inputData); - boolean asciiArmor = false; - if (outputData.getType() == OpenPgpData.TYPE_STRING) { - asciiArmor = true; - } - - // add own key for encryption - keyIds = Arrays.copyOf(keyIds, keyIds.length + 1); - keyIds[keyIds.length - 1] = appSettings.getKeyId(); - - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputDt = new InputData(inputStream, inputLength); - - OutputStream outputStream = new ByteArrayOutputStream(); - - PgpOperation operation = new PgpOperation(getContext(), null, inputDt, outputStream); - if (sign) { - String passphrase = getCachedPassphrase(appSettings.getKeyId(), - allowUserInteraction); - if (passphrase == null) { - throw new WrongPassphraseException("No or wrong passphrase!"); - } - - operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null, - appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(), - appSettings.getHashAlgorithm(), true, passphrase); - } else { - operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null, - appSettings.getEncryptionAlgorithm(), Id.key.none, - appSettings.getHashAlgorithm(), true, null); - } - - outputStream.close(); - - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - - OpenPgpData output = null; - if (asciiArmor) { - output = new OpenPgpData(new String(outputBytes)); - } else { - output = new OpenPgpData(outputBytes); - } - - // return over handler on client side - callback.onSuccess(output, null); - } catch (UserInteractionRequiredException e) { - callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage()); - } catch (WrongPassphraseException e) { - callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage()); - } catch (Exception e) { - callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage()); - } - } - - // TODO: asciiArmor?! - private void signSafe(byte[] inputBytes, boolean allowUserInteraction, - IOpenPgpCallback callback, AppSettings appSettings) { - try { - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); - - OutputStream outputStream = new ByteArrayOutputStream(); - - String passphrase = getCachedPassphrase(appSettings.getKeyId(), allowUserInteraction); - if (passphrase == null) { - throw new WrongPassphraseException("No or wrong passphrase!"); - } - - PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream); - operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(), - Preferences.getPreferences(this).getForceV3Signatures()); - - outputStream.close(); - - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - OpenPgpData output = new OpenPgpData(new String(outputBytes)); - - // return over handler on client side - callback.onSuccess(output, null); - } catch (UserInteractionRequiredException e) { - callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage()); - } catch (WrongPassphraseException e) { - callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage()); - } catch (Exception e) { - callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage()); - } - } - - private synchronized void decryptAndVerifySafe(byte[] inputBytes, boolean allowUserInteraction, - IOpenPgpCallback callback, AppSettings appSettings) { - try { - // TODO: this is not really needed - // checked if it is text with BEGIN and END tags - String message = new String(inputBytes); - Log.d(Constants.TAG, "in: " + message); - boolean signedOnly = false; - Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(message); - if (matcher.matches()) { - Log.d(Constants.TAG, "PGP_MESSAGE matched"); - message = matcher.group(1); - // replace non breakable spaces - message = message.replaceAll("\\xa0", " "); - - // overwrite inputBytes - inputBytes = message.getBytes(); - } else { - matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(message); - if (matcher.matches()) { - signedOnly = true; - Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched"); - message = matcher.group(1); - // replace non breakable spaces - message = message.replaceAll("\\xa0", " "); - - // overwrite inputBytes - inputBytes = message.getBytes(); - } else { - Log.d(Constants.TAG, "Nothing matched! Binary?"); - } - } - // END TODO - - Log.d(Constants.TAG, "in: " + new String(inputBytes)); - - // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the - // app, Fix this? - - String passphrase = null; - if (!signedOnly) { - // BEGIN Get key - // TODO: this input stream is consumed after PgpMain.getDecryptionKeyId()... do it - // better! - InputStream inputStream2 = new ByteArrayInputStream(inputBytes); - - // TODO: duplicates functions from DecryptActivity! - long secretKeyId; - try { - if (inputStream2.markSupported()) { - // should probably set this to the max size of two - // pgpF objects, if it even needs to be anything other - // than 0. - inputStream2.mark(200); - } - secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2); - if (secretKeyId == Id.key.none) { - throw new PgpGeneralException(getString(R.string.error_no_secret_key_found)); - } - } catch (NoAsymmetricEncryptionException e) { - if (inputStream2.markSupported()) { - inputStream2.reset(); - } - secretKeyId = Id.key.symmetric; - if (!PgpOperation.hasSymmetricEncryption(this, inputStream2)) { - throw new PgpGeneralException( - getString(R.string.error_no_known_encryption_found)); - } - // we do not support symmetric decryption from the API! - throw new Exception("Symmetric decryption is not supported!"); - } - - Log.d(Constants.TAG, "secretKeyId " + secretKeyId); - - passphrase = getCachedPassphrase(secretKeyId, allowUserInteraction); - if (passphrase == null) { - throw new WrongPassphraseException("No or wrong passphrase!"); - } - } - - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); - - OutputStream outputStream = new ByteArrayOutputStream(); - - Bundle outputBundle; - PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream); - if (signedOnly) { - // TODO: download missing keys from keyserver? - outputBundle = operation.verifyText(false); - } else { - outputBundle = operation.decryptAndVerify(passphrase, false); - } - - outputStream.close(); - - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - - // get signature informations from bundle - boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE); - - OpenPgpSignatureResult sigResult = null; - if (signature) { - long signatureKeyId = outputBundle - .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID); - String signatureUserId = outputBundle - .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID); - boolean signatureSuccess = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS); - boolean signatureUnknown = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN); - - int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR; - if (signatureSuccess) { - signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_TRUSTED; - } else if (signatureUnknown) { - signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY; - } - - sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId, - signedOnly, signatureKeyId); - } - OpenPgpData output = new OpenPgpData(new String(outputBytes)); - - // return over handler on client side - callback.onSuccess(output, sigResult); - } catch (UserInteractionRequiredException e) { - callbackOpenPgpError(callback, OpenPgpError.USER_INTERACTION_REQUIRED, e.getMessage()); - } catch (WrongPassphraseException e) { - callbackOpenPgpError(callback, OpenPgpError.NO_OR_WRONG_PASSPHRASE, e.getMessage()); - } catch (Exception e) { - callbackOpenPgpError(callback, OpenPgpError.GENERIC_ERROR, e.getMessage()); - } - } - - /** - * Returns error to IOpenPgpCallback - * - * @param callback - * @param errorId - * @param message - */ - private void callbackOpenPgpError(IOpenPgpCallback callback, int errorId, String message) { - try { - callback.onError(new OpenPgpError(0, message)); - } catch (Exception t) { - Log.e(Constants.TAG, - "Exception while returning OpenPgpError to client via callback.onError()", t); - } - } - - private void callbackOpenPgpError(IOpenPgpKeyIdsCallback callback, int errorId, String message) { - try { - callback.onError(new OpenPgpError(0, message)); - } catch (Exception t) { - Log.e(Constants.TAG, - "Exception while returning OpenPgpError to client via callback.onError()", t); - } - } - - private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() { - - @Override - public void encrypt(final OpenPgpData input, final OpenPgpData output, final long[] keyIds, - final IOpenPgpCallback callback) throws RemoteException { - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - encryptAndSignSafe(input, output, keyIds, true, callback, settings, false); - } - }; - - checkAndEnqueue(r); - } - - @Override - public void signAndEncrypt(final OpenPgpData input, final OpenPgpData output, - final long[] keyIds, final IOpenPgpCallback callback) throws RemoteException { - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - encryptAndSignSafe(input, output, keyIds, true, callback, settings, true); - } - }; - - checkAndEnqueue(r); - } - - @Override - public void sign(final OpenPgpData input, final OpenPgpData output, - final IOpenPgpCallback callback) throws RemoteException { - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - signSafe(getInput(input), true, callback, settings); - } - }; - - checkAndEnqueue(r); - } - - @Override - public void decryptAndVerify(final OpenPgpData input, final OpenPgpData output, - final IOpenPgpCallback callback) throws RemoteException { - - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - decryptAndVerifySafe(getInput(input), true, callback, settings); - } - }; - - checkAndEnqueue(r); - } - - @Override - public void getKeyIds(final String[] userIds, final boolean allowUserInteraction, - final IOpenPgpKeyIdsCallback callback) throws RemoteException { - - final AppSettings settings = getAppSettings(); - - Runnable r = new Runnable() { - @Override - public void run() { - getKeyIdsSafe(userIds, allowUserInteraction, callback, settings); - } - }; - - checkAndEnqueue(r); - } - - }; - - private static byte[] getInput(OpenPgpData data) { - // TODO: support Uri and ParcelFileDescriptor - - byte[] inBytes = null; - switch (data.getType()) { - case OpenPgpData.TYPE_STRING: - inBytes = data.getString().getBytes(); - break; - - case OpenPgpData.TYPE_BYTE_ARRAY: - inBytes = data.getBytes(); - break; - - default: - Log.e(Constants.TAG, "Uri and ParcelFileDescriptor not supported right now!"); - break; - } - - return inBytes; - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java deleted file mode 100644 index 477ee04d0..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsAdapter.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.database.Cursor; -import android.support.v4.widget.CursorAdapter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -public class RegisteredAppsAdapter extends CursorAdapter { - - private LayoutInflater mInflater; - private PackageManager pm; - - public RegisteredAppsAdapter(Context context, Cursor c, int flags) { - super(context, c, flags); - - mInflater = LayoutInflater.from(context); - pm = context.getApplicationContext().getPackageManager(); - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name); - ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon); - - String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME)); - if (packageName != null) { - // get application name - try { - ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - - text.setText(pm.getApplicationLabel(ai)); - icon.setImageDrawable(pm.getApplicationIcon(ai)); - } catch (final NameNotFoundException e) { - // fallback - text.setText(packageName); - } - } else { - // fallback - text.setText(packageName); - } - - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return mInflater.inflate(R.layout.api_apps_adapter_list_item, null); - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java deleted file mode 100644 index 3c553fff5..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.DrawerActivity; - -import android.os.Bundle; - -public class RegisteredAppsListActivity extends DrawerActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.api_apps_list_activity); - - setupDrawerNavigation(savedInstanceState); - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java deleted file mode 100644 index 4c9d553ad..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; - -import android.content.ContentUris; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; - -import com.actionbarsherlock.app.SherlockListFragment; - -public class RegisteredAppsListFragment extends SherlockListFragment implements - LoaderManager.LoaderCallbacks<Cursor> { - - // This is the Adapter being used to display the list's data. - RegisteredAppsAdapter mAdapter; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - getListView().setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { - // edit app settings - Intent intent = new Intent(getActivity(), AppSettingsActivity.class); - intent.setData(ContentUris.withAppendedId(KeychainContract.ApiApps.CONTENT_URI, id)); - startActivity(intent); - } - }); - - // Give some text to display if there is no data. In a real - // application this would come from a resource. - setEmptyText(getString(R.string.api_no_apps)); - - // We have a menu item to show in action bar. - setHasOptionsMenu(true); - - // Create an empty adapter we will use to display the loaded data. - mAdapter = new RegisteredAppsAdapter(getActivity(), null, 0); - setListAdapter(mAdapter); - - // Prepare the loader. Either re-connect with an existing one, - // or start a new one. - getLoaderManager().initLoader(0, null, this); - } - - // These are the Contacts rows that we will retrieve. - static final String[] PROJECTION = new String[] { ApiApps._ID, ApiApps.PACKAGE_NAME }; - - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - // This is called when a new Loader needs to be created. This - // sample only has one Loader, so we don't care about the ID. - // First, pick the base URI to use depending on whether we are - // currently filtering. - Uri baseUri = ApiApps.CONTENT_URI; - - // Now create and return a CursorLoader that will take care of - // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null, - ApiApps.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); - } - - public void onLoadFinished(Loader<Cursor> loader, Cursor data) { - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - mAdapter.swapCursor(data); - } - - public void onLoaderReset(Loader<Cursor> loader) { - // This is called when the last Cursor provided to onLoadFinished() - // above is about to be closed. We need to make sure we are no - // longer using it. - mAdapter.swapCursor(null); - } - -}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java deleted file mode 100644 index bc513d532..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteService.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.exception.WrongPackageSignatureException; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature; -import android.net.Uri; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; - -/** - * Abstract service class for remote APIs that handle app registration and user input. - */ -public abstract class RemoteService extends Service { - Context mContext; - - private final ArrayBlockingQueue<Runnable> mPoolQueue = new ArrayBlockingQueue<Runnable>(100); - // TODO: Are these parameters okay? - private PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10, - TimeUnit.SECONDS, mPoolQueue); - - private final Object userInputLock = new Object(); - - /** - * Override handleUserInput() to handle OKAY (1) and CANCEL (0). After handling the waiting - * threads will be notified and the queue resumed - */ - protected class UserInputCallback extends BaseCallback { - - public void handleUserInput(Message msg) { - } - - @Override - public boolean handleMessage(Message msg) { - handleUserInput(msg); - - // resume - synchronized (userInputLock) { - userInputLock.notifyAll(); - } - mThreadPool.resume(); - return true; - } - - } - - /** - * Extends Handler.Callback with OKAY (1), CANCEL (0) variables - */ - private class BaseCallback implements Handler.Callback { - public static final int OKAY = 1; - public static final int CANCEL = 0; - - @Override - public boolean handleMessage(Message msg) { - return false; - } - - } - - public Context getContext() { - return mContext; - } - - /** - * Should be used from Stub implementations of AIDL interfaces to enqueue a runnable for - * execution - * - * @param r - */ - protected void checkAndEnqueue(Runnable r) { - try { - if (isCallerAllowed(false)) { - mThreadPool.execute(r); - - Log.d(Constants.TAG, "Enqueued runnable…"); - } else { - String[] callingPackages = getPackageManager().getPackagesForUid( - Binder.getCallingUid()); - // TODO: currently simply uses first entry - String packageName = callingPackages[0]; - - byte[] packageSignature; - try { - packageSignature = getPackageSignature(packageName); - } catch (NameNotFoundException e) { - Log.e(Constants.TAG, "Should not happen, returning!", e); - return; - } - Log.e(Constants.TAG, - "Not allowed to use service! Starting activity for registration!"); - Bundle extras = new Bundle(); - extras.putString(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); - extras.putByteArray(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature); - RegisterActivityCallback callback = new RegisterActivityCallback(); - - pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_REGISTER, callback, - extras); - - if (callback.isAllowed()) { - mThreadPool.execute(r); - Log.d(Constants.TAG, "Enqueued runnable…"); - } else { - Log.d(Constants.TAG, "User disallowed app!"); - } - } - } catch (WrongPackageSignatureException e) { - Log.e(Constants.TAG, e.getMessage()); - - Bundle extras = new Bundle(); - extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, - getString(R.string.api_error_wrong_signature)); - pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null, extras); - } - } - - private byte[] getPackageSignature(String packageName) throws NameNotFoundException { - PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName, - PackageManager.GET_SIGNATURES); - Signature[] signatures = pkgInfo.signatures; - // TODO: Only first signature?! - byte[] packageSignature = signatures[0].toByteArray(); - - return packageSignature; - } - - /** - * Locks current thread and pauses execution of runnables and starts activity for user input - * - * @param action - * @param messenger - * @param extras - */ - protected void pauseAndStartUserInteraction(String action, BaseCallback callback, Bundle extras) { - synchronized (userInputLock) { - mThreadPool.pause(); - - Log.d(Constants.TAG, "starting activity..."); - Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setAction(action); - - Messenger messenger = new Messenger(new Handler(getMainLooper(), callback)); - - extras.putParcelable(RemoteServiceActivity.EXTRA_MESSENGER, messenger); - intent.putExtras(extras); - - startActivity(intent); - - // lock current thread for user input - try { - userInputLock.wait(); - } catch (InterruptedException e) { - Log.e(Constants.TAG, "CryptoService", e); - } - } - } - - /** - * Retrieves AppSettings from database for the application calling this remote service - * - * @return - */ - protected AppSettings getAppSettings() { - String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); - - // get app settings for this package - for (int i = 0; i < callingPackages.length; i++) { - String currentPkg = callingPackages[i]; - - Uri uri = KeychainContract.ApiApps.buildByPackageNameUri(currentPkg); - - AppSettings settings = ProviderHelper.getApiAppSettings(this, uri); - - if (settings != null) - return settings; - } - - return null; - } - - class RegisterActivityCallback extends BaseCallback { - public static final String PACKAGE_NAME = "package_name"; - - private boolean allowed = false; - private String packageName; - - public boolean isAllowed() { - return allowed; - } - - public String getPackageName() { - return packageName; - } - - @Override - public boolean handleMessage(Message msg) { - if (msg.arg1 == OKAY) { - allowed = true; - packageName = msg.getData().getString(PACKAGE_NAME); - - // resume threads - try { - if (isPackageAllowed(packageName)) { - synchronized (userInputLock) { - userInputLock.notifyAll(); - } - mThreadPool.resume(); - } else { - // Should not happen! - Log.e(Constants.TAG, "Should not happen! Emergency shutdown!"); - mThreadPool.shutdownNow(); - } - } catch (WrongPackageSignatureException e) { - Log.e(Constants.TAG, e.getMessage()); - - Bundle extras = new Bundle(); - extras.putString(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, - getString(R.string.api_error_wrong_signature)); - pauseAndStartUserInteraction(RemoteServiceActivity.ACTION_ERROR_MESSAGE, null, - extras); - } - } else { - allowed = false; - - synchronized (userInputLock) { - userInputLock.notifyAll(); - } - mThreadPool.resume(); - } - return true; - } - - } - - /** - * Checks if process that binds to this service (i.e. the package name corresponding to the - * process) is in the list of allowed package names. - * - * @param allowOnlySelf - * allow only Keychain app itself - * @return true if process is allowed to use this service - * @throws WrongPackageSignatureException - */ - private boolean isCallerAllowed(boolean allowOnlySelf) throws WrongPackageSignatureException { - return isUidAllowed(Binder.getCallingUid(), allowOnlySelf); - } - - private boolean isUidAllowed(int uid, boolean allowOnlySelf) - throws WrongPackageSignatureException { - if (android.os.Process.myUid() == uid) { - return true; - } - if (allowOnlySelf) { // barrier - return false; - } - - String[] callingPackages = getPackageManager().getPackagesForUid(uid); - - // is calling package allowed to use this service? - for (int i = 0; i < callingPackages.length; i++) { - String currentPkg = callingPackages[i]; - - if (isPackageAllowed(currentPkg)) { - return true; - } - } - - Log.d(Constants.TAG, "Caller is NOT allowed!"); - return false; - } - - /** - * Checks if packageName is a registered app for the API. Does not return true for own package! - * - * @param packageName - * @return - * @throws WrongPackageSignatureException - */ - private boolean isPackageAllowed(String packageName) throws WrongPackageSignatureException { - Log.d(Constants.TAG, "packageName: " + packageName); - - ArrayList<String> allowedPkgs = ProviderHelper.getRegisteredApiApps(this); - Log.d(Constants.TAG, "allowed: " + allowedPkgs); - - // check if package is allowed to use our service - if (allowedPkgs.contains(packageName)) { - Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); - - // check package signature - byte[] currentSig; - try { - currentSig = getPackageSignature(packageName); - } catch (NameNotFoundException e) { - throw new WrongPackageSignatureException(e.getMessage()); - } - - byte[] storedSig = ProviderHelper.getApiAppSignature(this, packageName); - if (Arrays.equals(currentSig, storedSig)) { - Log.d(Constants.TAG, - "Package signature is correct! (equals signature from database)"); - return true; - } else { - throw new WrongPackageSignatureException( - "PACKAGE NOT ALLOWED! Signature wrong! (Signature not equals signature from database)"); - } - } - - return false; - } - - @Override - public void onCreate() { - super.onCreate(); - mContext = this; - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java deleted file mode 100644 index de07989d8..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 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.remote; - -import java.util.ArrayList; - -import org.sufficientlysecure.htmltextview.HtmlTextView; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.view.View; -import android.widget.Toast; - -import com.actionbarsherlock.app.SherlockFragmentActivity; - -public class RemoteServiceActivity extends SherlockFragmentActivity { - - public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER"; - public static final String ACTION_CACHE_PASSPHRASE = Constants.INTENT_PREFIX - + "API_ACTIVITY_CACHE_PASSPHRASE"; - public static final String ACTION_SELECT_PUB_KEYS = Constants.INTENT_PREFIX - + "API_ACTIVITY_SELECT_PUB_KEYS"; - public static final String ACTION_ERROR_MESSAGE = Constants.INTENT_PREFIX - + "API_ACTIVITY_ERROR_MESSAGE"; - - public static final String EXTRA_MESSENGER = "messenger"; - - // passphrase action - public static final String EXTRA_SECRET_KEY_ID = "secret_key_id"; - // register action - public static final String EXTRA_PACKAGE_NAME = "package_name"; - public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature"; - // select pub keys action - public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids"; - public static final String EXTRA_MISSING_USER_IDS = "missing_user_ids"; - public static final String EXTRA_DUBLICATE_USER_IDS = "dublicate_user_ids"; - // error message - public static final String EXTRA_ERROR_MESSAGE = "error_message"; - - private Messenger mMessenger; - - // register view - private AppSettingsFragment mSettingsFragment; - // select pub keys view - private SelectPublicKeyFragment mSelectFragment; - - // has the user clicked one of the buttons - // or do we need to handle the callback in onStop() - private boolean finishHandled; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - handleActions(getIntent(), savedInstanceState); - } - - @Override - protected void onStop() { - super.onStop(); - - if (!finishHandled) { - Message msg = Message.obtain(); - msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - } - } - - protected void handleActions(Intent intent, Bundle savedInstanceState) { - finishHandled = false; - - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - mMessenger = extras.getParcelable(EXTRA_MESSENGER); - - /** - * com.android.crypto actions - */ - if (ACTION_REGISTER.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE); - - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.api_register_allow, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Allow - - // user needs to select a key! - if (mSettingsFragment.getAppSettings().getKeyId() == Id.key.none) { - Toast.makeText(RemoteServiceActivity.this, - R.string.api_register_error_select_key, Toast.LENGTH_LONG) - .show(); - } else { - ProviderHelper.insertApiApp(RemoteServiceActivity.this, - mSettingsFragment.getAppSettings()); - - Message msg = Message.obtain(); - msg.arg1 = RemoteService.RegisterActivityCallback.OKAY; - Bundle data = new Bundle(); - data.putString(RemoteService.RegisterActivityCallback.PACKAGE_NAME, - packageName); - msg.setData(data); - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - - finishHandled = true; - finish(); - } - } - }, R.string.api_register_disallow, new View.OnClickListener() { - @Override - public void onClick(View v) { - // Disallow - - Message msg = Message.obtain(); - msg.arg1 = RemoteService.RegisterActivityCallback.CANCEL; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - - finishHandled = true; - finish(); - } - }); - - setContentView(R.layout.api_app_register_activity); - - mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( - R.id.api_app_settings_fragment); - - AppSettings settings = new AppSettings(packageName, packageSignature); - mSettingsFragment.setAppSettings(settings); - } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { - long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); - - showPassphraseDialog(secretKeyId); - } else if (ACTION_SELECT_PUB_KEYS.equals(action)) { - long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); - ArrayList<String> missingUserIds = intent - .getStringArrayListExtra(EXTRA_MISSING_USER_IDS); - ArrayList<String> dublicateUserIds = intent - .getStringArrayListExtra(EXTRA_DUBLICATE_USER_IDS); - - String text = new String(); - text += "<b>" + getString(R.string.api_select_pub_keys_text) + "</b>"; - text += "<br/><br/>"; - if (missingUserIds != null && missingUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_missing_text); - text += "<br/>"; - text += "<ul>"; - for (String userId : missingUserIds) { - text += "<li>" + userId + "</li>"; - } - text += "</ul>"; - text += "<br/>"; - } - if (dublicateUserIds != null && dublicateUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_dublicates_text); - text += "<br/>"; - text += "<ul>"; - for (String userId : dublicateUserIds) { - text += "<li>" + userId + "</li>"; - } - text += "</ul>"; - } - - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_okay, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // ok - - Message msg = Message.obtain(); - msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.OKAY; - Bundle data = new Bundle(); - data.putLongArray( - OpenPgpService.SelectPubKeysActivityCallback.PUB_KEY_IDS, - mSelectFragment.getSelectedMasterKeyIds()); - msg.setData(data); - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - - finishHandled = true; - finish(); - } - }, R.string.btn_do_not_save, new View.OnClickListener() { - @Override - public void onClick(View v) { - // cancel - - Message msg = Message.obtain(); - msg.arg1 = OpenPgpService.SelectPubKeysActivityCallback.CANCEL; - ; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - - finishHandled = true; - finish(); - } - }); - - setContentView(R.layout.api_app_select_pub_keys_activity); - - // set text on view - HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_select_pub_keys_text); - textView.setHtmlFromString(text); - - /* Load select pub keys fragment */ - // Check that the activity is using the layout version with - // the fragment_container FrameLayout - if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) { - - // However, if we're being restored from a previous state, - // then we don't need to do anything and should return or else - // we could end up with overlapping fragments. - if (savedInstanceState != null) { - return; - } - - // Create an instance of the fragment - mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds); - - // Add the fragment to the 'fragment_container' FrameLayout - getSupportFragmentManager().beginTransaction() - .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit(); - } - } else if (ACTION_ERROR_MESSAGE.equals(action)) { - String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE); - - String text = new String(); - text += "<font color=\"red\">" + errorMessage + "</font>"; - - // Inflate a "Done" custom action bar view - ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_okay, - new View.OnClickListener() { - - @Override - public void onClick(View v) { - finish(); - } - }); - - setContentView(R.layout.api_app_error_message); - - // set text on view - HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_app_error_message_text); - textView.setHtmlFromString(text); - } else { - Log.e(Constants.TAG, "Wrong action!"); - finish(); - } - } - - /** - * Shows passphrase dialog to cache a new passphrase the user enters for using it later for - * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks - * for a symmetric passphrase - */ - private void showPassphraseDialog(long secretKeyId) { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - Message msg = Message.obtain(); - msg.arg1 = OpenPgpService.PassphraseActivityCallback.OKAY; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - } else { - Message msg = Message.obtain(); - msg.arg1 = OpenPgpService.PassphraseActivityCallback.CANCEL; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoServiceActivity", e); - } - } - - finishHandled = true; - finish(); - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - try { - PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, - messenger, secretKeyId); - - passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PgpGeneralException e) { - Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); - // send message to handler to start encryption directly - returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); - } - } -} |