From 703603782f2cc714cba04c057e4cc958e9768cb3 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 30 May 2017 19:06:28 +0200 Subject: [PATCH] tls-psk: actual import of keys --- .../network/KeyTransferInteractor.java | 14 ++-- .../keychain/operations/ImportOperation.java | 5 +- .../keychain/service/ImportKeyringParcel.java | 12 ++- .../transfer/presenter/TransferPresenter.java | 79 +++++++++++++++++-- .../transfer/view/ReceivedSecretKeyList.java | 9 ++- .../ui/transfer/view/TransferFragment.java | 59 ++++++++++---- .../src/main/res/layout/transfer_fragment.xml | 24 ------ 7 files changed, 139 insertions(+), 63 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/network/KeyTransferInteractor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/network/KeyTransferInteractor.java index a1b354d43..75ee873dd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/network/KeyTransferInteractor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/network/KeyTransferInteractor.java @@ -124,7 +124,7 @@ public class KeyTransferInteractor { serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(port); String presharedKeyEncoded = Base64.encodeToString(presharedKey, Base64.URL_SAFE | Base64.NO_PADDING); - String qrCodeData = presharedKeyEncoded + "@" + getIPAddress(true) + ":" + port; + String qrCodeData = "pgp+transfer://" + presharedKeyEncoded + "@" + getIPAddress(true) + ":" + port; invokeListener(CONNECTION_LISTENING, qrCodeData); socket = serverSocket.accept(); @@ -135,8 +135,8 @@ public class KeyTransferInteractor { } handleOpenConnection(socket); + Log.d(Constants.TAG, "connection closed ok!"); } catch (IOException e) { - invokeListener(CONNECTION_LOST, null); Log.e(Constants.TAG, "error!", e); } finally { try { @@ -176,13 +176,8 @@ public class KeyTransferInteractor { socket.setSoTimeout(500); while (!isInterrupted() && socket.isConnected()) { sendDataIfAvailable(socket, outputStream); - - boolean connectionClosed = receiveDataIfAvailable(socket, bufferedReader); - if (connectionClosed) { - break; - } + receiveDataIfAvailable(socket, bufferedReader); } - Log.d(Constants.TAG, "disconnected"); invokeListener(CONNECTION_LOST, null); } @@ -196,6 +191,7 @@ public class KeyTransferInteractor { } if (firstLine == null) { + invokeListener(CONNECTION_LOST, null); return true; } @@ -204,7 +200,7 @@ public class KeyTransferInteractor { socket.setSoTimeout(500); invokeListener(CONNECTION_RECEIVE_OK, receivedData); - return false; + return true; } private boolean sendDataIfAvailable(Socket socket, OutputStream outputStream) throws IOException { 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 4d584331a..a6bc0233b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java @@ -22,6 +22,7 @@ package org.sufficientlysecure.keychain.operations; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; @@ -477,7 +478,7 @@ public class ImportOperation extends BaseReadWriteOperation @NonNull @Override public ImportKeyResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) { - ArrayList keyList = importInput.getKeyList(); + List keyList = importInput.getKeyList(); HkpKeyserverAddress keyServer = importInput.getKeyserver(); boolean skipSave = importInput.isSkipSave(); @@ -510,7 +511,7 @@ public class ImportOperation extends BaseReadWriteOperation } @NonNull - private ImportKeyResult multiThreadedKeyImport(ArrayList keyList, + private ImportKeyResult multiThreadedKeyImport(List keyList, final HkpKeyserverAddress keyServer, final ParcelableProxy proxy, final boolean skipSave) { Log.d(Constants.TAG, "Multi-threaded key import starting"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ImportKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ImportKeyringParcel.java index 7b9c4f60d..e7a0e2d51 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ImportKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ImportKeyringParcel.java @@ -20,6 +20,8 @@ package org.sufficientlysecure.keychain.service; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import android.os.Parcelable; import android.support.annotation.Nullable; @@ -31,21 +33,25 @@ import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; @AutoValue public abstract class ImportKeyringParcel implements Parcelable { @Nullable // If null, keys are expected to be read from a cache file in ImportExportOperations - public abstract ArrayList getKeyList(); + public abstract List getKeyList(); @Nullable // must be set if keys are to be imported from a keyserver public abstract HkpKeyserverAddress getKeyserver(); public abstract boolean isSkipSave(); - public static ImportKeyringParcel createImportKeyringParcel(ArrayList keyList, + public static ImportKeyringParcel createImportKeyringParcel(List keyList, HkpKeyserverAddress keyserver) { return new AutoValue_ImportKeyringParcel(keyList, keyserver, false); } - public static ImportKeyringParcel createWithSkipSave(ArrayList keyList, + public static ImportKeyringParcel createWithSkipSave(List keyList, HkpKeyserverAddress keyserver) { return new AutoValue_ImportKeyringParcel(keyList, keyserver, true); } + public static ImportKeyringParcel createImportKeyringParcel(ParcelableKeyRing key) { + return new AutoValue_ImportKeyringParcel(Collections.singletonList(key), null, false); + } + public static ImportKeyringParcel createFromFileCacheWithSkipSave() { return new AutoValue_ImportKeyringParcel(null, null, true); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/presenter/TransferPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/presenter/TransferPresenter.java index 01d0a398a..d1c319f78 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/presenter/TransferPresenter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/presenter/TransferPresenter.java @@ -27,6 +27,7 @@ import android.net.Uri; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; +import android.os.Parcelable; import android.support.annotation.RequiresApi; import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager.LoaderCallbacks; @@ -37,12 +38,18 @@ import android.view.LayoutInflater; import org.openintents.openpgp.util.OpenPgpUtils; import org.openintents.openpgp.util.OpenPgpUtils.UserId; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.network.KeyTransferInteractor; import org.sufficientlysecure.keychain.network.KeyTransferInteractor.KeyTransferCallback; +import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException; +import org.sufficientlysecure.keychain.service.ImportKeyringParcel; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper.Callback; import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader.SecretKeyItem; import org.sufficientlysecure.keychain.ui.transfer.view.ReceivedSecretKeyList.OnClickImportKeyListener; import org.sufficientlysecure.keychain.ui.transfer.view.ReceivedSecretKeyList.ReceivedKeyAdapter; @@ -61,11 +68,14 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks op = + view.createCryptoOperationHelper(new Callback() { + @Override + public ImportKeyringParcel createOperationInput() { + return importKeyringParcel; + } + + @Override + public void onCryptoOperationSuccess(ImportKeyResult result) { + receivedKeyAdapter.focusItem(null); + receivedKeyAdapter.addToFinishedItems(masterKeyId); + view.releaseCryptoOperationHelper(); + view.showResultNotification(result); + } + + @Override + public void onCryptoOperationCancelled() { + view.releaseCryptoOperationHelper(); + receivedKeyAdapter.focusItem(null); + } + + @Override + public void onCryptoOperationError(ImportKeyResult result) { + receivedKeyAdapter.focusItem(null); + view.releaseCryptoOperationHelper(); + view.showResultNotification(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }); + + op.cryptoOperation(); } @Override public void onServerStarted(String qrCodeData) { - Bitmap qrCodeBitmap = QrCodeUtils.getQRCodeBitmap(Uri.parse("pgp+transfer://" + qrCodeData)); + Bitmap qrCodeBitmap = QrCodeUtils.getQRCodeBitmap(Uri.parse(qrCodeData)); view.setQrImage(qrCodeBitmap); } @Override public void onConnectionEstablished(String otherName) { + wasConnected = true; + secretKeyAdapter.clearFinishedItems(); view.showConnectionEstablished(otherName); } @Override public void onConnectionLost() { - connectionStartListen(); + if (!wasConnected) { + // display connection error? + connectionStartListen(); + view.showErrorConnectionFailed(); + } + // TODO handle error? } @Override @@ -152,7 +208,8 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks CryptoOperationHelper createCryptoOperationHelper(Callback callback); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/ReceivedSecretKeyList.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/ReceivedSecretKeyList.java index 12e6719a9..c0b6861c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/ReceivedSecretKeyList.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/ReceivedSecretKeyList.java @@ -87,6 +87,11 @@ public class ReceivedSecretKeyList extends RecyclerView { return data.get(position).masterKeyId; } + public void addToFinishedItems(long masterKeyId) { + finishedItems.add(masterKeyId); + // doeesn't notify, because it's non-trivial and this is called in conjunction with other refreshing things! + } + public void focusItem(Long masterKeyId) { focusedMasterKeyId = masterKeyId; notifyItemRangeChanged(0, getItemCount()); @@ -154,7 +159,7 @@ public class ReceivedSecretKeyList extends RecyclerView { vImportButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - onClickReceiveKeyListener.onUiClickImportKey(item.keyData); + onClickReceiveKeyListener.onUiClickImportKey(item.masterKeyId, item.keyData); } }); } else { @@ -164,7 +169,7 @@ public class ReceivedSecretKeyList extends RecyclerView { } public interface OnClickImportKeyListener { - void onUiClickImportKey(String keyData); + void onUiClickImportKey(long masterKeyId, String keyData); } public static class ReceivedKeyItem { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/TransferFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/TransferFragment.java index 94c343142..264125a34 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/TransferFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/transfer/view/TransferFragment.java @@ -18,16 +18,12 @@ package org.sufficientlysecure.keychain.ui.transfer.view; -import java.util.Timer; -import java.util.TimerTask; - import android.app.Activity; -import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.os.Build.VERSION_CODES; import android.os.Bundle; -import android.os.Handler; +import android.os.Parcelable; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.v4.app.Fragment; @@ -44,8 +40,12 @@ import android.widget.ViewAnimator; import com.google.zxing.client.android.Intents; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.ui.QrCodeCaptureActivity; -import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper.Callback; import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter; import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.TransferMvpView; @@ -54,8 +54,7 @@ import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.T public class TransferFragment extends Fragment implements TransferMvpView { public static final int VIEW_WAITING = 0; public static final int VIEW_CONNECTED = 1; - public static final int VIEW_SEND_OK = 2; - public static final int VIEW_RECEIVING = 3; + public static final int VIEW_RECEIVING = 2; public static final int REQUEST_CODE_SCAN = 1; public static final int LOADER_ID = 1; @@ -68,6 +67,8 @@ public class TransferFragment extends Fragment implements TransferMvpView { private RecyclerView vTransferKeyList; private RecyclerView vReceivedKeyList; + private CryptoOperationHelper currentCryptoOperationHelper; + @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -90,15 +91,9 @@ public class TransferFragment extends Fragment implements TransferMvpView { } }); - return view; - } - - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - presenter = new TransferPresenter(getContext(), getLoaderManager(), LOADER_ID, this); + + return view; } @Override @@ -162,8 +157,40 @@ public class TransferFragment extends Fragment implements TransferMvpView { vReceivedKeyList.setAdapter(adapter); } + @Override + public CryptoOperationHelper createCryptoOperationHelper(Callback callback) { + CryptoOperationHelper cryptoOperationHelper = new CryptoOperationHelper<>(1, this, callback, null); + currentCryptoOperationHelper = cryptoOperationHelper; + return cryptoOperationHelper; + } + + @Override + public void releaseCryptoOperationHelper() { + currentCryptoOperationHelper = null; + } + + @Override + public void showErrorBadKey() { + + } + + @Override + public void showErrorConnectionFailed() { + + } + + @Override + public void showResultNotification(ImportKeyResult result) { + result.createNotify(getActivity()).show(this); + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (currentCryptoOperationHelper != null && + currentCryptoOperationHelper.handleActivityResult(requestCode, resultCode, data)) { + return; + } + switch (requestCode) { case REQUEST_CODE_SCAN: if (resultCode == Activity.RESULT_OK) { diff --git a/OpenKeychain/src/main/res/layout/transfer_fragment.xml b/OpenKeychain/src/main/res/layout/transfer_fragment.xml index 1a9ff6dfb..1ab8d4b54 100644 --- a/OpenKeychain/src/main/res/layout/transfer_fragment.xml +++ b/OpenKeychain/src/main/res/layout/transfer_fragment.xml @@ -87,30 +87,6 @@ - - - - -