diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-08-28 11:00:18 +0200 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-08-28 11:00:18 +0200 |
commit | c0ebc926117d3e444c7c32bf3251880852000df6 (patch) | |
tree | b84926b3eee5cf1cfd6d38a2c3bec23e8f0b6779 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service | |
parent | ad69e47cec58287d82978b28416db50f6c3feb77 (diff) | |
parent | b193965e585d0d492cf2744e3c86ecc9e45b71d4 (diff) | |
download | open-keychain-c0ebc926117d3e444c7c32bf3251880852000df6.tar.gz open-keychain-c0ebc926117d3e444c7c32bf3251880852000df6.tar.bz2 open-keychain-c0ebc926117d3e444c7c32bf3251880852000df6.zip |
Merge branch 'master' into yubikey
Conflicts:
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service')
6 files changed, 321 insertions, 96 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 43ed2dad0..fbe914b78 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -21,6 +21,8 @@ import android.accounts.Account; import android.app.Service; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; +import android.content.ContentResolver; +import android.content.Context; import android.content.Intent; import android.content.SyncResult; import android.os.Bundle; @@ -29,9 +31,11 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; +import android.provider.ContactsContract; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.KeychainApplication; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.helper.EmailKeyHelper; import org.sufficientlysecure.keychain.util.Log; @@ -42,7 +46,7 @@ public class ContactSyncAdapterService extends Service { private class ContactSyncAdapter extends AbstractThreadedSyncAdapter { - private final AtomicBoolean importDone = new AtomicBoolean(false); +// private final AtomicBoolean importDone = new AtomicBoolean(false); public ContactSyncAdapter() { super(ContactSyncAdapterService.this, true); @@ -51,47 +55,59 @@ public class ContactSyncAdapterService extends Service { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, final SyncResult syncResult) { - importDone.set(false); - KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); - EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(), - new Handler.Callback() { - @Override - public boolean handleMessage(Message msg) { - Bundle data = msg.getData(); - switch (msg.arg1) { - case KeychainIntentServiceHandler.MESSAGE_OKAY: - Log.d(Constants.TAG, "Syncing... Done."); - synchronized (importDone) { - importDone.set(true); - importDone.notifyAll(); - } - return true; - case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS: - if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) && - data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) { - Log.d(Constants.TAG, "Syncing... Progress: " + - data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" + - data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)); - return false; - } - default: - Log.d(Constants.TAG, "Syncing... " + msg.toString()); - return false; - } - } - }))); - synchronized (importDone) { - try { - if (!importDone.get()) importDone.wait(); - } catch (InterruptedException e) { - Log.w(Constants.TAG, e); - return; - } - } + Log.d(Constants.TAG, "Performing a sync!"); + // TODO: Import is currently disabled for 2.8, until we implement proper origin management +// importDone.set(false); +// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); +// EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(), +// new Handler.Callback() { +// @Override +// public boolean handleMessage(Message msg) { +// Bundle data = msg.getData(); +// switch (msg.arg1) { +// case KeychainIntentServiceHandler.MESSAGE_OKAY: +// Log.d(Constants.TAG, "Syncing... Done."); +// synchronized (importDone) { +// importDone.set(true); +// importDone.notifyAll(); +// } +// return true; +// case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS: +// if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) && +// data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) { +// Log.d(Constants.TAG, "Syncing... Progress: " + +// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" + +// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)); +// return false; +// } +// default: +// Log.d(Constants.TAG, "Syncing... " + msg.toString()); +// return false; +// } +// } +// }))); +// synchronized (importDone) { +// try { +// if (!importDone.get()) importDone.wait(); +// } catch (InterruptedException e) { +// Log.w(Constants.TAG, e); +// return; +// } +// } ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this); } } + public static void requestSync() { + Bundle extras = new Bundle(); + // no need to wait for internet connection! + extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); + ContentResolver.requestSync( + new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), + ContactsContract.AUTHORITY, + extras); + } + @Override public IBinder onBind(Intent intent) { return new ContactSyncAdapter().getSyncAdapterBinder(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d6c470e11..021e6bc07 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,11 +50,14 @@ import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; +import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -102,6 +106,10 @@ public class KeychainIntentService extends IntentService public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; + public static final String ACTION_DELETE = Constants.INTENT_PREFIX + "DELETE"; + + public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE"; + /* keys for data bundle */ // encrypt, decrypt, import export @@ -139,8 +147,13 @@ public class KeychainIntentService extends IntentService // delete file securely public static final String DELETE_FILE = "deleteFile"; + // delete keyring(s) + public static final String DELETE_KEY_LIST = "delete_list"; + public static final String DELETE_IS_SECRET = "delete_is_secret"; + // import key public static final String IMPORT_KEY_LIST = "import_key_list"; + public static final String IMPORT_KEY_FILE = "import_key_file"; // export key public static final String EXPORT_OUTPUT_STREAM = "export_output_stream"; @@ -162,6 +175,10 @@ public class KeychainIntentService extends IntentService public static final String CERTIFY_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; public static final String CERTIFY_KEY_UIDS = "sign_key_uids"; + // consolidate + public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery"; + + /* * possible data keys as result send over messenger */ @@ -176,8 +193,6 @@ public class KeychainIntentService extends IntentService // export public static final String RESULT_EXPORT = "exported"; - public static final String RESULT_IMPORT = "result"; - Messenger mMessenger; private boolean mIsCanceled; @@ -246,27 +261,31 @@ public class KeychainIntentService extends IntentService String originalFilename = getOriginalFilename(data); /* Operation */ - PgpSignEncrypt.Builder builder = - new PgpSignEncrypt.Builder( - new ProviderHelper(this), - inputData, outStream); - builder.setProgressable(this); - - builder.setEnableAsciiArmorOutput(useAsciiArmor) + PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( + new ProviderHelper(this), + inputData, outStream + ); + builder.setProgressable(this) + .setEnableAsciiArmorOutput(useAsciiArmor) .setVersionHeader(PgpHelper.getVersionForHeader(this)) .setCompressionId(compressionId) .setSymmetricEncryptionAlgorithm( Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) .setEncryptionMasterKeyIds(encryptionKeyIds) .setSymmetricPassphrase(symmetricPassphrase) - .setSignatureMasterKeyId(signatureKeyId) - .setEncryptToSigner(true) - .setSignatureHashAlgorithm( - Preferences.getPreferences(this).getDefaultHashAlgorithm()) - .setSignaturePassphrase( - PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)) .setOriginalFilename(originalFilename); + try { + builder.setSignatureMasterKeyId(signatureKeyId) + .setSignaturePassphrase( + PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)) + .setSignatureHashAlgorithm( + Preferences.getPreferences(this).getDefaultHashAlgorithm()) + .setAdditionalEncryptId(signatureKeyId); + } catch (PassphraseCacheService.KeyNotFoundException e) { + // encrypt-only + } + // this assumes that the bytes are cleartext (valid for current implementation!) if (source == IO_BYTES) { builder.setCleartextInput(true); @@ -391,23 +410,41 @@ public class KeychainIntentService extends IntentService } /* Operation */ - ProviderHelper providerHelper = new ProviderHelper(this); PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 60, 100)); - EditKeyResult result; + EditKeyResult modifyResult; if (saveParcel.mMasterKeyId != null) { String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE); CanonicalizedSecretKeyRing secRing = - providerHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId); + new ProviderHelper(this).getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId); - result = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase); + modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase); } else { - result = keyOperations.createSecretKeyRing(saveParcel); + modifyResult = keyOperations.createSecretKeyRing(saveParcel); } - UncachedKeyRing ring = result.getRing(); + // If the edit operation didn't succeed, exit here + if (!modifyResult.success()) { + // always return SaveKeyringResult, so create one out of the EditKeyResult + SaveKeyringResult saveResult = new SaveKeyringResult( + SaveKeyringResult.RESULT_ERROR, + modifyResult.getLog(), + null); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); + return; + } - providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); + UncachedKeyRing ring = modifyResult.getRing(); + + // Save the keyring. The ProviderHelper is initialized with the previous log + SaveKeyringResult saveResult = new ProviderHelper(this, modifyResult.getLog()) + .saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); + + // If the edit operation didn't succeed, exit here + if (!saveResult.success()) { + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); + return; + } // cache new passphrase if (saveParcel.mNewPassphrase != null) { @@ -417,8 +454,11 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(); + /* Output */ - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); } catch (Exception e) { sendErrorToHandler(e); } @@ -454,17 +494,21 @@ public class KeychainIntentService extends IntentService } else { // get entries from cached file FileImportCache<ParcelableKeyRing> cache = - new FileImportCache<ParcelableKeyRing>(this); + new FileImportCache<ParcelableKeyRing>(this, "key_import.pcl"); entries = cache.readCacheIntoList(); } - PgpImportExport pgpImportExport = new PgpImportExport(this, this); + ProviderHelper providerHelper = new ProviderHelper(this); + PgpImportExport pgpImportExport = new PgpImportExport(this, providerHelper, this); ImportKeyResult result = pgpImportExport.importKeyRings(entries); - Bundle resultData = new Bundle(); - resultData.putParcelable(RESULT_IMPORT, result); + if (result.mSecret > 0) { + providerHelper.consolidateDatabaseStep1(this); + } + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(); - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } catch (Exception e) { sendErrorToHandler(e); } @@ -549,8 +593,9 @@ public class KeychainIntentService extends IntentService CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri); PgpImportExport pgpImportExport = new PgpImportExport(this, null); - boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, keyring); - if (!uploaded) { + try { + pgpImportExport.uploadKeyRingToServer(server, keyring); + } catch (Keyserver.AddKeyException e) { throw new PgpGeneralException("Unable to export key to selected server"); } @@ -639,7 +684,56 @@ public class KeychainIntentService extends IntentService } catch (Exception e) { sendErrorToHandler(e); } + + } else if (ACTION_DELETE.equals(action)) { + + try { + + long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST); + boolean isSecret = data.getBoolean(DELETE_IS_SECRET); + + if (masterKeyIds.length == 0) { + throw new PgpGeneralException("List of keys to delete is empty"); + } + + if (isSecret && masterKeyIds.length > 1) { + throw new PgpGeneralException("Secret keys can only be deleted individually!"); + } + + boolean success = false; + for (long masterKeyId : masterKeyIds) { + int count = getContentResolver().delete( + KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null + ); + success |= count > 0; + } + + if (isSecret && success) { + ConsolidateResult result = + new ProviderHelper(this).consolidateDatabaseStep1(this); + } + + if (success) { + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(); + + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); + } + + } catch (Exception e) { + sendErrorToHandler(e); + } + + } else if (ACTION_CONSOLIDATE.equals(action)) { + ConsolidateResult result; + if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) { + result = new ProviderHelper(this).consolidateDatabaseStep2(this); + } else { + result = new ProviderHelper(this).consolidateDatabaseStep1(this); + } + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } + } private void sendErrorToHandler(Exception e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index d7d98fd68..142bf65cc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -155,10 +156,8 @@ public class OperationResultParcel implements Parcelable { if ((resultType & OperationResultParcel.RESULT_ERROR) == 0) { if (getLog().containsWarnings()) { - duration = 0; color = Style.ORANGE; } else { - duration = SuperToast.Duration.LONG; color = Style.GREEN; } @@ -167,7 +166,6 @@ public class OperationResultParcel implements Parcelable { } else { - duration = 0; color = Style.RED; str = "operation failed"; @@ -180,8 +178,8 @@ public class OperationResultParcel implements Parcelable { button ? SuperToast.Type.BUTTON : SuperToast.Type.STANDARD, Style.getStyle(color, SuperToast.Animations.POPUP)); toast.setText(str); - toast.setDuration(duration); - toast.setIndeterminate(duration == 0); + toast.setDuration(SuperToast.Duration.EXTRA_LONG); + toast.setIndeterminate(false); toast.setSwipeToDismiss(true); // If we have a log and it's non-empty, show a View Log button if (button) { @@ -289,6 +287,7 @@ public class OperationResultParcel implements Parcelable { MSG_IS_SUCCESS (R.string.msg_is_success), // keyring canonicalization + MSG_KC_V3_KEY (R.string.msg_kc_v3_key), MSG_KC_PUBLIC (R.string.msg_kc_public), MSG_KC_SECRET (R.string.msg_kc_secret), MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid), @@ -324,6 +323,7 @@ public class OperationResultParcel implements Parcelable { MSG_KC_UID_BAD_TIME (R.string.msg_kc_uid_bad_time), MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type), MSG_KC_UID_BAD (R.string.msg_kc_uid_bad), + MSG_KC_UID_CERT_DUP (R.string.msg_kc_uid_cert_dup), MSG_KC_UID_DUP (R.string.msg_kc_uid_dup), MSG_KC_UID_FOREIGN (R.string.msg_kc_uid_foreign), MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert), @@ -333,10 +333,11 @@ public class OperationResultParcel implements Parcelable { // keyring consolidation + MSG_MG_ERROR_SECRET_DUMMY(R.string.msg_mg_error_secret_dummy), + MSG_MG_ERROR_ENCODE(R.string.msg_mg_error_encode), + MSG_MG_ERROR_HETEROGENEOUS(R.string.msg_mg_error_heterogeneous), MSG_MG_PUBLIC (R.string.msg_mg_public), MSG_MG_SECRET (R.string.msg_mg_secret), - MSG_MG_FATAL_ENCODE (R.string.msg_mg_fatal_encode), - MSG_MG_HETEROGENEOUS (R.string.msg_mg_heterogeneous), MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey), MSG_MG_FOUND_NEW (R.string.msg_mg_found_new), MSG_MG_UNCHANGED (R.string.msg_mg_unchanged), @@ -346,10 +347,16 @@ public class OperationResultParcel implements Parcelable { MSG_CR_ERROR_NO_MASTER (R.string.msg_cr_error_no_master), MSG_CR_ERROR_NO_USER_ID (R.string.msg_cr_error_no_user_id), MSG_CR_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), + MSG_CR_ERROR_NULL_EXPIRY(R.string.msg_cr_error_null_expiry), MSG_CR_ERROR_KEYSIZE_512 (R.string.msg_cr_error_keysize_512), + MSG_CR_ERROR_NO_KEYSIZE (R.string.msg_cr_error_no_keysize), + MSG_CR_ERROR_NO_CURVE (R.string.msg_cr_error_no_curve), MSG_CR_ERROR_UNKNOWN_ALGO (R.string.msg_cr_error_unknown_algo), MSG_CR_ERROR_INTERNAL_PGP (R.string.msg_cr_error_internal_pgp), - MSG_CR_ERROR_MASTER_ELGAMAL (R.string.msg_cr_error_master_elgamal), + MSG_CR_ERROR_FLAGS_DSA (R.string.msg_cr_error_flags_dsa), + MSG_CR_ERROR_FLAGS_ELGAMAL (R.string.msg_cr_error_flags_elgamal), + MSG_CR_ERROR_FLAGS_ECDSA (R.string.msg_cr_error_flags_ecdsa), + MSG_CR_ERROR_FLAGS_ECDH (R.string.msg_cr_error_flags_ecdh), // secret key modify MSG_MF (R.string.msg_mr), @@ -357,18 +364,27 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint), MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), + MSG_MF_ERROR_MASTER_NONE(R.string.msg_mf_error_master_none), + MSG_MF_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), - MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), + MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), + MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry), + MSG_MF_ERROR_PASSPHRASE_MASTER(R.string.msg_mf_error_passphrase_master), + MSG_MF_ERROR_PAST_EXPIRY(R.string.msg_mf_error_past_expiry), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), + MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), + MSG_MF_ERROR_SUBKEY_MISSING(R.string.msg_mf_error_subkey_missing), + MSG_MF_MASTER (R.string.msg_mf_master), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), + MSG_MF_PASSPHRASE_KEY (R.string.msg_mf_passphrase_key), + MSG_MF_PASSPHRASE_EMPTY_RETRY (R.string.msg_mf_passphrase_empty_retry), + MSG_MF_PASSPHRASE_FAIL (R.string.msg_mf_passphrase_fail), MSG_MF_PRIMARY_REPLACE_OLD (R.string.msg_mf_primary_replace_old), MSG_MF_PRIMARY_NEW (R.string.msg_mf_primary_new), MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change), - MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing), MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id), MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new), - MSG_MF_SUBKEY_PAST_EXPIRY (R.string.msg_mf_subkey_past_expiry), MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke), MSG_MF_SUCCESS (R.string.msg_mf_success), MSG_MF_UID_ADD (R.string.msg_mf_uid_add), @@ -377,6 +393,32 @@ public class OperationResultParcel implements Parcelable { MSG_MF_UID_ERROR_EMPTY (R.string.msg_mf_uid_error_empty), MSG_MF_UNLOCK_ERROR (R.string.msg_mf_unlock_error), MSG_MF_UNLOCK (R.string.msg_mf_unlock), + + // consolidate + MSG_CON_CRITICAL_IN (R.string.msg_con_critical_in), + MSG_CON_CRITICAL_OUT (R.string.msg_con_critical_out), + MSG_CON_DB_CLEAR (R.string.msg_con_db_clear), + MSG_CON_DELETE_PUBLIC (R.string.msg_con_delete_public), + MSG_CON_DELETE_SECRET (R.string.msg_con_delete_secret), + MSG_CON_ERROR_BAD_STATE (R.string.msg_con_error_bad_state), + MSG_CON_ERROR_CONCURRENT(R.string.msg_con_error_concurrent), + MSG_CON_ERROR_DB (R.string.msg_con_error_db), + MSG_CON_ERROR_IO_PUBLIC (R.string.msg_con_error_io_public), + MSG_CON_ERROR_IO_SECRET (R.string.msg_con_error_io_secret), + MSG_CON_ERROR_PUBLIC (R.string.msg_con_error_public), + MSG_CON_ERROR_SECRET (R.string.msg_con_error_secret), + MSG_CON_RECOVER (R.plurals.msg_con_recover), + MSG_CON_RECOVER_UNKNOWN (R.string.msg_con_recover_unknown), + MSG_CON_REIMPORT_PUBLIC (R.plurals.msg_con_reimport_public), + MSG_CON_REIMPORT_PUBLIC_SKIP (R.string.msg_con_reimport_public_skip), + MSG_CON_REIMPORT_SECRET (R.plurals.msg_con_reimport_secret), + MSG_CON_REIMPORT_SECRET_SKIP (R.string.msg_con_reimport_secret_skip), + MSG_CON (R.string.msg_con), + MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public), + MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret), + MSG_CON_SUCCESS (R.string.msg_con_success), + MSG_CON_WARN_DELETE_PUBLIC (R.string.msg_con_warn_delete_public), + MSG_CON_WARN_DELETE_SECRET (R.string.msg_con_warn_delete_secret), ; private final int mMsgId; @@ -406,7 +448,9 @@ public class OperationResultParcel implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mResult); - dest.writeTypedList(mLog.toList()); + if (mLog != null) { + dest.writeTypedList(mLog.toList()); + } } public static final Creator<OperationResultParcel> CREATOR = new Creator<OperationResultParcel>() { @@ -432,6 +476,15 @@ public class OperationResultParcel implements Parcelable { mParcels.add(new OperationResultParcel.LogEntryParcel(level, type, indent, (Object[]) null)); } + public boolean containsType(LogType type) { + for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) { + if (entry.mType == type) { + return true; + } + } + return false; + } + public boolean containsWarnings() { for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) { if (entry.mLevel == LogLevel.WARN || entry.mLevel == LogLevel.ERROR) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 543b83edb..f3d0b9e9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +29,10 @@ import com.github.johnpersano.supertoasts.SuperToast; import com.github.johnpersano.supertoasts.util.OnClickWrapper; import com.github.johnpersano.supertoasts.util.Style; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; @@ -37,7 +41,7 @@ public abstract class OperationResults { public static class ImportKeyResult extends OperationResultParcel { - public final int mNewKeys, mUpdatedKeys, mBadKeys; + public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret; // At least one new key public static final int RESULT_OK_NEWKEYS = 2; @@ -49,18 +53,21 @@ public abstract class OperationResults { public static final int RESULT_WITH_WARNINGS = 16; // No keys to import... - public static final int RESULT_FAIL_NOTHING = 32 +1; + public static final int RESULT_FAIL_NOTHING = 32 + 1; public boolean isOkBoth() { return (mResult & (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED)) == (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED); } + public boolean isOkNew() { return (mResult & RESULT_OK_NEWKEYS) == RESULT_OK_NEWKEYS; } + public boolean isOkUpdated() { return (mResult & RESULT_OK_UPDATED) == RESULT_OK_UPDATED; } + public boolean isFailNothing() { return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING; } @@ -70,14 +77,16 @@ public abstract class OperationResults { mNewKeys = source.readInt(); mUpdatedKeys = source.readInt(); mBadKeys = source.readInt(); + mSecret = source.readInt(); } public ImportKeyResult(int result, OperationLog log, - int newKeys, int updatedKeys, int badKeys) { + int newKeys, int updatedKeys, int badKeys, int secret) { super(result, log); mNewKeys = newKeys; mUpdatedKeys = updatedKeys; mBadKeys = badKeys; + mSecret = secret; } @Override @@ -86,6 +95,7 @@ public abstract class OperationResults { dest.writeInt(mNewKeys); dest.writeInt(mUpdatedKeys); dest.writeInt(mBadKeys); + dest.writeInt(mSecret); } public static Creator<ImportKeyResult> CREATOR = new Creator<ImportKeyResult>() { @@ -124,7 +134,7 @@ public abstract class OperationResults { if (this.isOkBoth()) { str = activity.getResources().getQuantityString( R.plurals.import_keys_added_and_updated_1, mNewKeys, mNewKeys); - str += " "+ activity.getResources().getQuantityString( + str += " " + activity.getResources().getQuantityString( R.plurals.import_keys_added_and_updated_2, mUpdatedKeys, mUpdatedKeys, withWarnings); } else if (isOkUpdated()) { str = activity.getResources().getQuantityString( @@ -185,13 +195,13 @@ public abstract class OperationResults { public static class EditKeyResult extends OperationResultParcel { private transient UncachedKeyRing mRing; - public final Long mRingMasterKeyId; + public final long mRingMasterKeyId; public EditKeyResult(int result, OperationLog log, - UncachedKeyRing ring) { + UncachedKeyRing ring) { super(result, log); mRing = ring; - mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null; + mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none; } public UncachedKeyRing getRing() { @@ -224,8 +234,12 @@ public abstract class OperationResults { public static class SaveKeyringResult extends OperationResultParcel { - public SaveKeyringResult(int result, OperationLog log) { + public final long mRingMasterKeyId; + + public SaveKeyringResult(int result, OperationLog log, + CanonicalizedKeyRing ring) { super(result, log); + mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none; } // Some old key was updated @@ -240,6 +254,34 @@ public abstract class OperationResults { return (mResult & UPDATED) == UPDATED; } + public SaveKeyringResult(Parcel source) { + super(source); + mRingMasterKeyId = source.readLong(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeLong(mRingMasterKeyId); + } + + public static Creator<SaveKeyringResult> CREATOR = new Creator<SaveKeyringResult>() { + public SaveKeyringResult createFromParcel(final Parcel source) { + return new SaveKeyringResult(source); + } + + public SaveKeyringResult[] newArray(final int size) { + return new SaveKeyringResult[size]; + } + }; + } + + public static class ConsolidateResult extends OperationResultParcel { + + public ConsolidateResult(int result, OperationLog log) { + super(result, log); + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 8cd9876eb..1b357bd65 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -78,7 +78,7 @@ public class PassphraseCacheService extends Service { private static final int NOTIFICATION_ID = 1; private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1; - private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND = 2; + private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2; private BroadcastReceiver mIntentReceiver; @@ -170,7 +170,7 @@ public class PassphraseCacheService extends Service { switch (returnMessage.what) { case MSG_PASSPHRASE_CACHE_GET_OKAY: return returnMessage.getData().getString(EXTRA_PASSPHRASE); - case MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND: + case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND: throw new KeyNotFoundException(); default: throw new KeyNotFoundException("should not happen!"); @@ -322,7 +322,7 @@ public class PassphraseCacheService extends Service { msg.setData(bundle); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "PassphraseCacheService: Passphrase for unknown key was requested!"); - msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND; + msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND; } try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 490a8e738..996ce6a5a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -79,14 +80,16 @@ public class SaveKeyringParcel implements Parcelable { // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { - public int mAlgorithm; - public int mKeysize; + public Algorithm mAlgorithm; + public Integer mKeySize; + public Curve mCurve; public int mFlags; public Long mExpiry; - public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { + public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) { mAlgorithm = algorithm; - mKeysize = keysize; + mKeySize = keySize; + mCurve = curve; mFlags = flags; mExpiry = expiry; } @@ -94,7 +97,8 @@ public class SaveKeyringParcel implements Parcelable { @Override public String toString() { String out = "mAlgorithm: " + mAlgorithm + ", "; - out += "mKeysize: " + mKeysize + ", "; + out += "mKeySize: " + mKeySize + ", "; + out += "mCurve: " + mCurve + ", "; out += "mFlags: " + mFlags; out += "mExpiry: " + mExpiry; @@ -213,4 +217,20 @@ public class SaveKeyringParcel implements Parcelable { return out; } + + // All supported algorithms + public enum Algorithm { + RSA, DSA, ELGAMAL, ECDSA, ECDH + } + + // All curves defined in the standard + // http://www.bouncycastle.org/wiki/pages/viewpage.action?pageId=362269 + public enum Curve { + NIST_P256, NIST_P384, NIST_P521, + + // these are supported by gpg, but they are not in rfc6637 and not supported by BouncyCastle yet + // (adding support would be trivial though -> JcaPGPKeyConverter.java:190) + // BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512 + } + } |