diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations')
14 files changed, 245 insertions, 105 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java index fae59b7a4..a8d1f0313 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; import android.os.Parcelable; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface; @@ -76,9 +77,8 @@ public abstract class BaseOperation <T extends Parcelable> implements Passphrase mCancelled = cancelled; } - public OperationResult execute(T input, CryptoInputParcel cryptoInput) { - return null; - } + @NonNull + public abstract OperationResult execute(T input, CryptoInputParcel cryptoInput); public void updateProgress(int message, int current, int total) { if (mProgressable != null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index 0806e6a16..318eee6ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -18,11 +18,11 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import android.support.annotation.NonNull; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; -import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.operations.results.CertifyResult; +import org.sufficientlysecure.keychain.operations.results.ExportResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; @@ -43,27 +43,31 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; +import java.net.Proxy; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; -/** An operation which implements a high level user id certification operation. - * +/** + * An operation which implements a high level user id certification operation. + * <p/> * This operation takes a specific CertifyActionsParcel as its input. These * contain a masterKeyId to be used for certification, and a list of * masterKeyIds and related user ids to certify. * * @see CertifyActionsParcel - * */ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { - public CertifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable, AtomicBoolean cancelled) { + public CertifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable, AtomicBoolean + cancelled) { super(context, providerHelper, progressable, cancelled); } + @NonNull @Override public CertifyResult execute(CertifyActionsParcel parcel, CryptoInputParcel cryptoInput) { @@ -174,7 +178,7 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { } - if ( ! allRequiredInput.isEmpty()) { + if (!allRequiredInput.isEmpty()) { log.add(LogType.MSG_CRT_NFC_RETURN, 1); return new CertifyResult(log, allRequiredInput.build()); } @@ -187,11 +191,24 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { return new CertifyResult(CertifyResult.RESULT_CANCELLED, log); } + // these variables are used inside the following loop, but they need to be created only once HkpKeyserver keyServer = null; ExportOperation exportOperation = null; + Proxy proxy = null; if (parcel.keyServerUri != null) { keyServer = new HkpKeyserver(parcel.keyServerUri); exportOperation = new ExportOperation(mContext, mProviderHelper, mProgressable); + if (cryptoInput.getParcelableProxy() == null) { + // explicit proxy not set + if (!OrbotHelper.isOrbotInRequiredState(mContext)) { + return new CertifyResult(null, + RequiredInputParcel.createOrbotRequiredOperation()); + } + proxy = Preferences.getPreferences(mContext).getProxyPrefs() + .parcelableProxy.getProxy(); + } else { + proxy = cryptoInput.getParcelableProxy().getProxy(); + } } // Write all certified keys into the database @@ -200,7 +217,8 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { // Check if we were cancelled if (checkCancelled()) { log.add(LogType.MSG_OPERATION_CANCELLED, 0); - return new CertifyResult(CertifyResult.RESULT_CANCELLED, log, certifyOk, certifyError, uploadOk, uploadError); + return new CertifyResult(CertifyResult.RESULT_CANCELLED, log, certifyOk, certifyError, uploadOk, + uploadError); } log.add(LogType.MSG_CRT_SAVE, 2, @@ -210,12 +228,15 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { SaveKeyringResult result = mProviderHelper.savePublicKeyRing(certifiedKey); if (exportOperation != null) { - // TODO use subresult, get rid of try/catch! - try { - exportOperation.uploadKeyRingToServer(keyServer, certifiedKey); + ExportResult uploadResult = exportOperation.uploadKeyRingToServer( + keyServer, + certifiedKey, + proxy); + log.add(uploadResult, 2); + + if (uploadResult.success()) { uploadOk += 1; - } catch (AddKeyException e) { - Log.e(Constants.TAG, "error uploading key", e); + } else { uploadError += 1; } } @@ -227,19 +248,24 @@ public class CertifyOperation extends BaseOperation<CertifyActionsParcel> { } log.add(result, 2); - } if (certifyOk == 0) { log.add(LogType.MSG_CRT_ERROR_NOTHING, 0); - return new CertifyResult(CertifyResult.RESULT_ERROR, log, certifyOk, certifyError, uploadOk, uploadError); + return new CertifyResult(CertifyResult.RESULT_ERROR, log, certifyOk, certifyError, + uploadOk, uploadError); } - log.add(LogType.MSG_CRT_SUCCESS, 0); - //since only verified keys are synced to contacts, we need to initiate a sync now + // since only verified keys are synced to contacts, we need to initiate a sync now ContactSyncAdapterService.requestSync(); - - return new CertifyResult(CertifyResult.RESULT_OK, log, certifyOk, certifyError, uploadOk, uploadError); + + log.add(LogType.MSG_CRT_SUCCESS, 0); + if (uploadError != 0) { + return new CertifyResult(CertifyResult.RESULT_WARNINGS, log, certifyOk, certifyError, uploadOk, + uploadError); + } else { + return new CertifyResult(CertifyResult.RESULT_OK, log, certifyOk, certifyError, uploadOk, uploadError); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ConsolidateOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ConsolidateOperation.java index bda574e0a..782cd6800 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ConsolidateOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ConsolidateOperation.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.pgp.Progressable; @@ -34,6 +35,7 @@ public class ConsolidateOperation extends BaseOperation<ConsolidateInputParcel> super(context, providerHelper, progressable); } + @NonNull @Override public ConsolidateResult execute(ConsolidateInputParcel consolidateInputParcel, CryptoInputParcel cryptoInputParcel) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java index 50b2ef69b..ac4a0da11 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.operations.results.DeleteResult; @@ -45,6 +46,7 @@ public class DeleteOperation extends BaseOperation<DeleteKeyringParcel> { super(context, providerHelper, progressable); } + @NonNull @Override public DeleteResult execute(DeleteKeyringParcel deleteKeyringParcel, CryptoInputParcel cryptoInputParcel) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index db34a149b..eafbff4bc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; @@ -57,6 +58,7 @@ public class EditKeyOperation extends BaseOperation<SaveKeyringParcel> { super(context, providerHelper, progressable, cancelled); } + @NonNull public OperationResult execute(SaveKeyringParcel saveParcel, CryptoInputParcel cryptoInput) { OperationLog log = new OperationLog(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java index 01a45bc79..a82e16461 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java @@ -21,12 +21,14 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.support.annotation.NonNull; import org.spongycastle.bcpg.ArmoredOutputStream; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; +import org.sufficientlysecure.keychain.operations.results.CertifyResult; import org.sufficientlysecure.keychain.operations.results.ExportResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; @@ -40,9 +42,12 @@ import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ExportKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; @@ -51,6 +56,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.net.Proxy; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -62,7 +68,6 @@ import java.util.concurrent.atomic.AtomicBoolean; * @see org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter#getSelectedEntries() * For the export operation, the input consists of a set of key ids and * either the name of a file or an output uri to write to. - * TODO rework uploadKeyRingToServer */ public class ExportOperation extends BaseOperation<ExportKeyringParcel> { @@ -76,25 +81,39 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> { super(context, providerHelper, progressable, cancelled); } - public void uploadKeyRingToServer(HkpKeyserver server, CanonicalizedPublicKeyRing keyring) - throws AddKeyException { - uploadKeyRingToServer(server, keyring.getUncachedKeyRing()); + public ExportResult uploadKeyRingToServer(HkpKeyserver server, CanonicalizedPublicKeyRing keyring, + Proxy proxy) { + return uploadKeyRingToServer(server, keyring.getUncachedKeyRing(), proxy); } - public void uploadKeyRingToServer(HkpKeyserver server, UncachedKeyRing keyring) throws - AddKeyException { + public ExportResult uploadKeyRingToServer(HkpKeyserver server, UncachedKeyRing keyring, Proxy proxy) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ArmoredOutputStream aos = null; + OperationLog log = new OperationLog(); + log.add(LogType.MSG_EXPORT_UPLOAD_PUBLIC, 0, KeyFormattingUtils.convertKeyIdToHex( + keyring.getPublicKey().getKeyId() + )); + try { aos = new ArmoredOutputStream(bos); keyring.encode(aos); aos.close(); String armoredKey = bos.toString("UTF-8"); - server.add(armoredKey); + server.add(armoredKey, proxy); + + log.add(LogType.MSG_EXPORT_UPLOAD_SUCCESS, 1); + return new ExportResult(ExportResult.RESULT_OK, log); } catch (IOException e) { Log.e(Constants.TAG, "IOException", e); - throw new AddKeyException(); + + log.add(LogType.MSG_EXPORT_ERROR_KEY, 1); + return new ExportResult(ExportResult.RESULT_ERROR, log); + } catch (AddKeyException e) { + Log.e(Constants.TAG, "AddKeyException", e); + + log.add(LogType.MSG_EXPORT_ERROR_UPLOAD, 1); + return new ExportResult(ExportResult.RESULT_ERROR, log); } finally { try { if (aos != null) { @@ -311,20 +330,32 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> { } + @NonNull public ExportResult execute(ExportKeyringParcel exportInput, CryptoInputParcel cryptoInput) { switch (exportInput.mExportType) { case UPLOAD_KEYSERVER: { + Proxy proxy; + if (cryptoInput.getParcelableProxy() == null) { + // explicit proxy not set + if (!OrbotHelper.isOrbotInRequiredState(mContext)) { + return new ExportResult(null, + RequiredInputParcel.createOrbotRequiredOperation()); + } + proxy = Preferences.getPreferences(mContext).getProxyPrefs() + .parcelableProxy.getProxy(); + } else { + proxy = cryptoInput.getParcelableProxy().getProxy(); + } + HkpKeyserver hkpKeyserver = new HkpKeyserver(exportInput.mKeyserver); try { CanonicalizedPublicKeyRing keyring = mProviderHelper.getCanonicalizedPublicKeyRing( exportInput.mCanonicalizedPublicKeyringUri); - uploadKeyRingToServer(hkpKeyserver, keyring); - // TODO: replace with proper log - return new ExportResult(ExportResult.RESULT_OK, new OperationLog()); - } catch (Exception e) { + return uploadKeyRingToServer(hkpKeyserver, keyring, proxy); + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "error uploading key", e); return new ExportResult(ExportResult.RESULT_ERROR, new OperationLog()); - // TODO: Implement better exception handling, replace with log } } case EXPORT_FILE: { @@ -335,8 +366,8 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> { return exportToUri(exportInput.mMasterKeyIds, exportInput.mExportSecret, exportInput.mOutputUri); } - default: { // can't happen - return null; + default: { // can never happen, all enum types must be handled above + throw new AssertionError("must not happen, this is a bug!"); } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java index ace059dac..a89b46cca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java @@ -18,7 +18,24 @@ package org.sufficientlysecure.keychain.operations; + +import java.io.IOException; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import android.content.Context; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -39,24 +56,13 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.ProgressScaler; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; /** * An operation class which implements high level import @@ -89,39 +95,40 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { // Overloaded functions for using progressable supplied in constructor during import public ImportKeyResult serialKeyRingImport(Iterator<ParcelableKeyRing> entries, int num, - String keyServerUri) { - return serialKeyRingImport(entries, num, keyServerUri, mProgressable); + String keyServerUri, Proxy proxy) { + return serialKeyRingImport(entries, num, keyServerUri, mProgressable, proxy); } public ImportKeyResult serialKeyRingImport(List<ParcelableKeyRing> entries, - String keyServerUri) { + String keyServerUri, Proxy proxy) { Iterator<ParcelableKeyRing> it = entries.iterator(); int numEntries = entries.size(); - return serialKeyRingImport(it, numEntries, keyServerUri, mProgressable); + return serialKeyRingImport(it, numEntries, keyServerUri, mProgressable, proxy); } public ImportKeyResult serialKeyRingImport(List<ParcelableKeyRing> entries, String keyServerUri, - Progressable progressable) { + Progressable progressable, Proxy proxy) { Iterator<ParcelableKeyRing> it = entries.iterator(); int numEntries = entries.size(); - return serialKeyRingImport(it, numEntries, keyServerUri, progressable); + return serialKeyRingImport(it, numEntries, keyServerUri, progressable, proxy); } + @NonNull public ImportKeyResult serialKeyRingImport(ParcelableFileCache<ParcelableKeyRing> cache, - String keyServerUri) { + String keyServerUri, Proxy proxy) { // get entries from cached file try { IteratorWithSize<ParcelableKeyRing> it = cache.readCache(); int numEntries = it.getSize(); - return serialKeyRingImport(it, numEntries, keyServerUri, mProgressable); + return serialKeyRingImport(it, numEntries, keyServerUri, mProgressable, proxy); } catch (IOException e) { // Special treatment here, we need a lot @@ -143,10 +150,11 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { * @param keyServerUri contains uri of keyserver to import from, if it is an import from cloud * @param progressable Allows multi-threaded import to supply a progressable that ignores the * progress of a single key being imported - * @return */ + @NonNull public ImportKeyResult serialKeyRingImport(Iterator<ParcelableKeyRing> entries, int num, - String keyServerUri, Progressable progressable) { + String keyServerUri, Progressable progressable, + Proxy proxy) { updateProgress(R.string.progress_importing, 0, 100); OperationLog log = new OperationLog(); @@ -208,10 +216,11 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { if (entry.mExpectedFingerprint != null) { log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER, 2, "0x" + entry.mExpectedFingerprint.substring(24)); - data = keyServer.get("0x" + entry.mExpectedFingerprint).getBytes(); + data = keyServer.get("0x" + entry.mExpectedFingerprint, proxy) + .getBytes(); } else { log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER, 2, entry.mKeyIdHex); - data = keyServer.get(entry.mKeyIdHex).getBytes(); + data = keyServer.get(entry.mKeyIdHex, proxy).getBytes(); } key = UncachedKeyRing.decodeFromData(data); if (key != null) { @@ -234,7 +243,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { try { log.add(LogType.MSG_IMPORT_FETCH_KEYBASE, 2, entry.mKeybaseName); - byte[] data = keybaseServer.get(entry.mKeybaseName).getBytes(); + byte[] data = keybaseServer.get(entry.mKeybaseName, proxy).getBytes(); UncachedKeyRing keybaseKey = UncachedKeyRing.decodeFromData(data); // If there already is a key, merge the two @@ -373,12 +382,11 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { importedMasterKeyIdsArray); } + @NonNull @Override - public ImportKeyResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) { - return importKeys(importInput.mKeyList, importInput.mKeyserver); - } - - public ImportKeyResult importKeys(ArrayList<ParcelableKeyRing> keyList, String keyServer) { + public OperationResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) { + ArrayList<ParcelableKeyRing> keyList = importInput.mKeyList; + String keyServer = importInput.mKeyserver; ImportKeyResult result; @@ -386,8 +394,21 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { ParcelableFileCache<ParcelableKeyRing> cache = new ParcelableFileCache<>(mContext, "key_import.pcl"); - result = serialKeyRingImport(cache, keyServer); + result = serialKeyRingImport(cache, null, null); } else { + Proxy proxy; + if (cryptoInput.getParcelableProxy() == null) { + // explicit proxy not set + if(!OrbotHelper.isOrbotInRequiredState(mContext)) { + // show dialog to enable/install dialog + return new ImportKeyResult(null, + RequiredInputParcel.createOrbotRequiredOperation()); + } + proxy = Preferences.getPreferences(mContext).getProxyPrefs().parcelableProxy + .getProxy(); + } else { + proxy = cryptoInput.getParcelableProxy().getProxy(); + } // if there is more than one key with the same fingerprint, we do a serial import to // prevent // https://github.com/open-keychain/open-keychain/issues/1221 @@ -397,9 +418,10 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { } if (keyFingerprintSet.size() == keyList.size()) { // all keys have unique fingerprints - result = multiThreadedKeyImport(keyList.iterator(), keyList.size(), keyServer); + result = multiThreadedKeyImport(keyList.iterator(), keyList.size(), keyServer, + proxy); } else { - result = serialKeyRingImport(keyList, keyServer); + result = serialKeyRingImport(keyList, keyServer, proxy); } } @@ -407,8 +429,10 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { return result; } + @NonNull private ImportKeyResult multiThreadedKeyImport(Iterator<ParcelableKeyRing> keyListIterator, - int totKeys, final String keyServer) { + int totKeys, final String keyServer, + final Proxy proxy) { Log.d(Constants.TAG, "Multi-threaded key import starting"); if (keyListIterator != null) { KeyImportAccumulator accumulator = new KeyImportAccumulator(totKeys, mProgressable); @@ -421,7 +445,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { new SynchronousQueue<Runnable>()); ExecutorCompletionService<ImportKeyResult> importCompletionService = - new ExecutorCompletionService(importExecutor); + new ExecutorCompletionService<>(importExecutor); while (keyListIterator.hasNext()) { // submit all key rings to be imported @@ -436,7 +460,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { ArrayList<ParcelableKeyRing> list = new ArrayList<>(); list.add(pkRing); - return serialKeyRingImport(list, keyServer, ignoreProgressable); + return serialKeyRingImport(list, keyServer, ignoreProgressable, proxy); } }; @@ -562,4 +586,4 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> { } } -}
\ No newline at end of file +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java index 57b99951d..42bd3ace2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java @@ -19,7 +19,15 @@ package org.sufficientlysecure.keychain.operations; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.List; + import android.content.Context; +import android.support.annotation.NonNull; import com.textuality.keybase.lib.Proof; import com.textuality.keybase.lib.prover.Prover; @@ -41,11 +49,9 @@ import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificationParcel> { @@ -54,9 +60,22 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat super(context, providerHelper, progressable); } + @NonNull @Override public KeybaseVerificationResult execute(KeybaseVerificationParcel keybaseInput, CryptoInputParcel cryptoInput) { + Proxy proxy; + if (cryptoInput.getParcelableProxy() == null) { + // explicit proxy not set + if (!OrbotHelper.isOrbotInRequiredState(mContext)) { + return new KeybaseVerificationResult(null, + RequiredInputParcel.createOrbotRequiredOperation()); + } + proxy = Preferences.getPreferences(mContext).getProxyPrefs() + .parcelableProxy.getProxy(); + } else { + proxy = cryptoInput.getParcelableProxy().getProxy(); + } String requiredFingerprint = keybaseInput.mRequiredFingerprint; @@ -76,7 +95,7 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log); } - if (!prover.fetchProofData()) { + if (!prover.fetchProofData(proxy)) { log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FETCH_PROOF, 1); return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log); } @@ -96,7 +115,7 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log); } Record[] records = dnsQuery.getAnswers(); - List<List<byte[]>> extents = new ArrayList<List<byte[]>>(); + List<List<byte[]>> extents = new ArrayList<>(); for (Record r : records) { Data d = r.getPayload(); if (d instanceof TXT) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java index 6291f14a3..2f25b6926 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java @@ -17,7 +17,11 @@ package org.sufficientlysecure.keychain.operations; + +import java.util.concurrent.atomic.AtomicBoolean; + import android.content.Context; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; @@ -36,8 +40,6 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ProgressScaler; -import java.util.concurrent.atomic.AtomicBoolean; - /** An operation which promotes a public key ring to a secret one. * * This operation can only be applied to public key rings where no secret key @@ -52,18 +54,10 @@ public class PromoteKeyOperation extends BaseOperation<PromoteKeyringParcel> { super(context, providerHelper, progressable, cancelled); } + @NonNull @Override public PromoteKeyResult execute(PromoteKeyringParcel promoteKeyringParcel, CryptoInputParcel cryptoInputParcel) { - // Input - long masterKeyId = promoteKeyringParcel.mKeyRingId; - byte[] cardAid = promoteKeyringParcel.mCardAid; - long[] subKeyIds = promoteKeyringParcel.mSubKeyIds; - - return execute(masterKeyId, cardAid, subKeyIds); - } - - public PromoteKeyResult execute(long masterKeyId, byte[] cardAid, long[] subKeyIds) { OperationLog log = new OperationLog(); log.add(LogType.MSG_PR, 0); @@ -74,17 +68,17 @@ public class PromoteKeyOperation extends BaseOperation<PromoteKeyringParcel> { try { log.add(LogType.MSG_PR_FETCHING, 1, - KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); + KeyFormattingUtils.convertKeyIdToHex(promoteKeyringParcel.mKeyRingId)); CanonicalizedPublicKeyRing pubRing = - mProviderHelper.getCanonicalizedPublicKeyRing(masterKeyId); + mProviderHelper.getCanonicalizedPublicKeyRing(promoteKeyringParcel.mKeyRingId); - if (subKeyIds == null) { + if (promoteKeyringParcel.mSubKeyIds == null) { log.add(LogType.MSG_PR_ALL, 1); } else { // sort for binary search for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) { long subKeyId = key.getKeyId(); - if (naiveIndexOf(subKeyIds, subKeyId) != null) { + if (naiveIndexOf(promoteKeyringParcel.mSubKeyIds, subKeyId) != null) { log.add(LogType.MSG_PR_SUBKEY_MATCH, 1, KeyFormattingUtils.convertKeyIdToHex(subKeyId)); } else { @@ -95,7 +89,8 @@ public class PromoteKeyOperation extends BaseOperation<PromoteKeyringParcel> { } // create divert-to-card secret key from public key - promotedRing = pubRing.createDivertSecretRing(cardAid, subKeyIds); + promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.mCardAid, + promoteKeyringParcel.mSubKeyIds); } catch (NotFoundException e) { log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java index 8fe5b86c5..f7f968d16 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; import android.net.Uri; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; @@ -36,6 +37,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSign import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType; import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.InputData; +import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayInputStream; @@ -61,6 +63,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> { super(context, providerHelper, progressable, cancelled); } + @NonNull public SignEncryptResult execute(SignEncryptParcel input, CryptoInputParcel cryptoInput) { OperationLog log = new OperationLog(); @@ -84,7 +87,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> { input.getSignatureMasterKeyId()).getSecretSignId(); input.setSignatureSubKeyId(signKeyId); } catch (PgpKeyNotFoundException e) { - e.printStackTrace(); + Log.e(Constants.TAG, "Key not found", e); return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java index c8edce259..199a3f565 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java @@ -19,7 +19,9 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; -public class ExportResult extends OperationResult { +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; + +public class ExportResult extends InputPendingResult { final int mOkPublic, mOkSecret; @@ -33,6 +35,14 @@ public class ExportResult extends OperationResult { mOkSecret = okSecret; } + + public ExportResult(OperationLog log, RequiredInputParcel requiredInputParcel) { + super(log, requiredInputParcel); + // we won't use these values + mOkPublic = -1; + mOkSecret = -1; + } + /** Construct from a parcel - trivial because we have no extra data. */ public ExportResult(Parcel source) { super(source); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java index 2a032cef2..ca7079078 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java @@ -23,6 +23,8 @@ import android.content.Intent; import android.os.Parcel; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; import org.sufficientlysecure.keychain.ui.util.Notify; @@ -30,7 +32,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener; import org.sufficientlysecure.keychain.ui.util.Notify.Showable; import org.sufficientlysecure.keychain.ui.util.Notify.Style; -public class ImportKeyResult extends OperationResult { +public class ImportKeyResult extends InputPendingResult { public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret; public final long[] mImportedMasterKeyIds; @@ -80,7 +82,7 @@ public class ImportKeyResult extends OperationResult { } public ImportKeyResult(int result, OperationLog log) { - this(result, log, 0, 0, 0, 0, new long[] { }); + this(result, log, 0, 0, 0, 0, new long[]{}); } public ImportKeyResult(int result, OperationLog log, @@ -94,6 +96,16 @@ public class ImportKeyResult extends OperationResult { mImportedMasterKeyIds = importedMasterKeyIds; } + public ImportKeyResult(OperationLog log, RequiredInputParcel requiredInputParcel) { + super(log, requiredInputParcel); + // just assign default values, we won't use them anyway + mNewKeys = 0; + mUpdatedKeys = 0; + mBadKeys = 0; + mSecret = 0; + mImportedMasterKeyIds = new long[]{}; + } + @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java index 420cbbf01..173f7f575 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java @@ -24,7 +24,9 @@ import android.os.Parcelable; import com.textuality.keybase.lib.KeybaseException; import com.textuality.keybase.lib.prover.Prover; -public class KeybaseVerificationResult extends OperationResult implements Parcelable { +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; + +public class KeybaseVerificationResult extends InputPendingResult { public final String mProofUrl; public final String mPresenceUrl; public final String mPresenceLabel; @@ -44,6 +46,13 @@ public class KeybaseVerificationResult extends OperationResult implements Parcel mPresenceLabel = prover.getPresenceLabel(); } + public KeybaseVerificationResult(OperationLog log, RequiredInputParcel requiredInputParcel) { + super(log, requiredInputParcel); + mProofUrl = null; + mPresenceUrl = null; + mPresenceLabel = null; + } + protected KeybaseVerificationResult(Parcel in) { super(in); mProofUrl = in.readString(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 245623762..5ae068b35 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -609,6 +609,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_ERROR_INTEGRITY_MISSING (LogLevel.ERROR, R.string.msg_dc_error_integrity_missing), MSG_DC_ERROR_INVALID_DATA (LogLevel.ERROR, R.string.msg_dc_error_invalid_data), MSG_DC_ERROR_IO (LogLevel.ERROR, R.string.msg_dc_error_io), + MSG_DC_ERROR_INPUT (LogLevel.ERROR, R.string.msg_dc_error_input), MSG_DC_ERROR_NO_DATA (LogLevel.ERROR, R.string.msg_dc_error_no_data), MSG_DC_ERROR_NO_KEY (LogLevel.ERROR, R.string.msg_dc_error_no_key), MSG_DC_ERROR_PGP_EXCEPTION (LogLevel.ERROR, R.string.msg_dc_error_pgp_exception), @@ -692,6 +693,7 @@ public abstract class OperationResult implements Parcelable { MSG_CRT_WARN_NOT_FOUND (LogLevel.WARN, R.string.msg_crt_warn_not_found), MSG_CRT_WARN_CERT_FAILED (LogLevel.WARN, R.string.msg_crt_warn_cert_failed), MSG_CRT_WARN_SAVE_FAILED (LogLevel.WARN, R.string.msg_crt_warn_save_failed), + MSG_CRT_WARN_UPLOAD_FAILED (LogLevel.WARN, R.string.msg_crt_warn_upload_failed), MSG_IMPORT (LogLevel.START, R.plurals.msg_import), @@ -712,6 +714,7 @@ public abstract class OperationResult implements Parcelable { MSG_IMPORT_SUCCESS (LogLevel.OK, R.string.msg_import_success), MSG_EXPORT (LogLevel.START, R.plurals.msg_export), + MSG_EXPORT_UPLOAD_PUBLIC (LogLevel.START, R.string.msg_export_upload_public), MSG_EXPORT_PUBLIC (LogLevel.DEBUG, R.string.msg_export_public), MSG_EXPORT_SECRET (LogLevel.DEBUG, R.string.msg_export_secret), MSG_EXPORT_ALL (LogLevel.START, R.string.msg_export_all), @@ -723,7 +726,9 @@ public abstract class OperationResult implements Parcelable { MSG_EXPORT_ERROR_DB (LogLevel.ERROR, R.string.msg_export_error_db), MSG_EXPORT_ERROR_IO (LogLevel.ERROR, R.string.msg_export_error_io), MSG_EXPORT_ERROR_KEY (LogLevel.ERROR, R.string.msg_export_error_key), + MSG_EXPORT_ERROR_UPLOAD (LogLevel.ERROR, R.string.msg_export_error_upload), MSG_EXPORT_SUCCESS (LogLevel.OK, R.string.msg_export_success), + MSG_EXPORT_UPLOAD_SUCCESS (LogLevel.OK, R.string.msg_export_upload_success), MSG_CRT_UPLOAD_SUCCESS (LogLevel.OK, R.string.msg_crt_upload_success), |