aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-09-28 18:27:29 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-09-28 18:27:29 +0200
commit0e613aff2e617ca12c1b2e1032b21334c2ca674a (patch)
tree4e16d6a086cbe12875454fba520241ac84e277c7 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util
parentb65a23f2d46f905160b47e044de12cf9177dfd51 (diff)
parent3df9bea4554c0edddce57aa6a2e32cfe5250ed72 (diff)
downloadopen-keychain-0e613aff2e617ca12c1b2e1032b21334c2ca674a.tar.gz
open-keychain-0e613aff2e617ca12c1b2e1032b21334c2ca674a.tar.bz2
open-keychain-0e613aff2e617ca12c1b2e1032b21334c2ca674a.zip
Merge remote-tracking branch 'origin/master' into encrypted-export
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java84
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/OkHttpKeybaseClient.java79
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java82
7 files changed, 146 insertions, 138 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
index d7491ab26..9a6d33260 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
@@ -103,8 +103,7 @@ public class EmailKeyHelper {
}
}
}
- } catch (Keyserver.QueryFailedException ignored) {
- } catch (Keyserver.QueryNeedsRepairException ignored) {
+ } catch (Keyserver.CloudSearchFailureException ignored) {
}
return new ArrayList<>(keys);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
index 2e0b0af36..cc90c173f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
@@ -69,13 +69,14 @@ public class ExportHelper
: R.string.specify_backup_dest_single);
}
- FileHelper.saveDocumentDialog(new FileHelper.FileDialogCallback() {
- @Override
- public void onFileSelected(File file, boolean checked) {
- mExportFile = file;
- exportKeys(masterKeyId == null ? null : new long[] { masterKeyId }, exportSecret);
- }
- }, mActivity.getSupportFragmentManager(), title, message, exportFile, null);
+ // TODO: for valodim
+// FileHelper.saveDocumentDialog(new FileHelper.FileDialogCallback() {
+// @Override
+// public void onFileSelected(File file, boolean checked) {
+// mExportFile = file;
+// exportKeys(masterKeyId == null ? null : new long[] { masterKeyId }, exportSecret);
+// }
+// }, mActivity.getSupportFragmentManager(), title, message, exportFile, null);
}
// TODO: If ExportHelper requires pending data (see CryptoOPerationHelper), activities using
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
index 9fb362412..fea3e65b6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.util;
import android.annotation.TargetApi;
-import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,20 +29,13 @@ import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
import android.widget.Toast;
-import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
-import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -82,52 +74,26 @@ import java.text.DecimalFormat;
public class FileHelper {
public static void openDocument(Fragment fragment, Uri last, String mimeType, boolean multiple, int requestCode) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- openDocumentPreKitKat(fragment, last, mimeType, multiple, requestCode);
- } else {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
openDocumentKitKat(fragment, mimeType, multiple, requestCode);
+ } else {
+ openDocumentPreKitKat(fragment, last, mimeType, multiple, requestCode);
}
}
- public static void saveDocument(Fragment fragment, String targetName, Uri inputUri,
- @StringRes int title, @StringRes int message, int requestCode) {
- saveDocument(fragment, targetName, inputUri, "*/*", title, message, requestCode);
+ public static void saveDocument(Fragment fragment, String targetName, int requestCode) {
+ saveDocument(fragment, targetName, "*/*", requestCode);
}
- public static void saveDocument(Fragment fragment, String targetName, Uri inputUri, String mimeType,
- @StringRes int title, @StringRes int message, int requestCode) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- saveDocumentDialog(fragment, targetName, inputUri, title, message, requestCode);
- } else {
+ public static void saveDocument(Fragment fragment, String targetName, String mimeType,
+ int requestCode) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
saveDocumentKitKat(fragment, mimeType, targetName, requestCode);
+ } else {
+ throw new RuntimeException("saveDocument does not support Android < 4.4!");
}
}
- public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
- @StringRes int title, @StringRes int message, final int requestCode) {
-
- saveDocumentDialog(fragment, targetName, inputUri, title, message, new FileDialogCallback() {
- // is this a good idea? seems hacky...
- @Override
- public void onFileSelected(File file, boolean checked) {
- Intent intent = new Intent();
- intent.setData(Uri.fromFile(file));
- fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
- }
- });
- }
-
- public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
- @StringRes int title, @StringRes int message, FileDialogCallback callback) {
-
- File file = inputUri == null ? null : new File(inputUri.getPath());
- File parentDir = file != null && file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- File targetFile = new File(parentDir, targetName);
- saveDocumentDialog(callback, fragment.getActivity().getSupportFragmentManager(),
- fragment.getString(title), fragment.getString(message), targetFile, null);
-
- }
-
/** Opens the preferred installed file manager on Android and shows a toast
* if no manager is installed. */
private static void openDocumentPreKitKat(
@@ -172,36 +138,6 @@ public class FileHelper {
fragment.startActivityForResult(intent, requestCode);
}
- public static void saveDocumentDialog(
- final FileDialogCallback callback, final FragmentManager fragmentManager,
- final String title, final String message, final File defaultFile,
- final String checkMsg) {
- // Message is received after file is selected
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == FileDialogFragment.MESSAGE_OKAY) {
- callback.onFileSelected(
- new File(message.getData().getString(FileDialogFragment.MESSAGE_DATA_FILE)),
- message.getData().getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED));
- }
- }
- };
-
- // Create a new Messenger for the communication back
- final Messenger messenger = new Messenger(returnHandler);
-
- DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
- @Override
- public void run() {
- FileDialogFragment fileDialog = FileDialogFragment.newInstance(messenger, title, message,
- defaultFile, checkMsg);
-
- fileDialog.show(fragmentManager, "fileDialog");
- }
- });
- }
-
public static String getFilename(Context context, Uri uri) {
String filename = null;
try {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java
index ab73f59b8..d06f2ab65 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2015 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.util;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
index 2b47fd623..1040e683b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
@@ -141,6 +141,10 @@ public class NfcHelper {
}
protected void onPostExecute(Void unused) {
+ if (mActivity.isFinishing()) {
+ return;
+ }
+
// Register callback to set NDEF message
mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
mActivity);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/OkHttpKeybaseClient.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/OkHttpKeybaseClient.java
new file mode 100644
index 000000000..32a5406e0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/OkHttpKeybaseClient.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 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.util;
+
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.OkUrlFactory;
+import com.textuality.keybase.lib.KeybaseUrlConnectionClient;
+
+import org.sufficientlysecure.keychain.Constants;
+
+import java.io.IOException;
+import java.net.Proxy;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Wrapper for Keybase Lib
+ */
+public class OkHttpKeybaseClient implements KeybaseUrlConnectionClient {
+
+ private final OkUrlFactory factory;
+
+ private static OkUrlFactory generateUrlFactory() {
+ OkHttpClient client = new OkHttpClient();
+ return new OkUrlFactory(client);
+ }
+
+ public OkHttpKeybaseClient() {
+ factory = generateUrlFactory();
+ }
+
+ @Override
+ public URLConnection openConnection(URL url) throws IOException {
+ return openConnection(url, null);
+ }
+
+ @Override
+ public URLConnection openConnection(URL url, Proxy proxy) throws IOException {
+ if (proxy != null) {
+ factory.client().setProxy(proxy);
+ factory.client().setConnectTimeout(30000, TimeUnit.MILLISECONDS);
+ factory.client().setReadTimeout(40000, TimeUnit.MILLISECONDS);
+ } else {
+ factory.client().setConnectTimeout(5000, TimeUnit.MILLISECONDS);
+ factory.client().setReadTimeout(25000, TimeUnit.MILLISECONDS);
+ }
+
+ factory.client().setFollowSslRedirects(false);
+
+ // forced the usage of keybase.io pinned certificate
+ try {
+ if (!TlsHelper.usePinnedCertificateIfAvailable(factory.client(), url)) {
+ throw new IOException("no pinned certificate found for URL!");
+ }
+ } catch (TlsHelper.TlsHelperException e) {
+ Log.e(Constants.TAG, "TlsHelper failed", e);
+ throw new IOException("TlsHelper failed");
+ }
+
+ return factory.open(url);
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
index d1d1ada2a..1492abdeb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2015 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
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.util;
import android.content.res.AssetManager;
import com.squareup.okhttp.OkHttpClient;
+
import org.sufficientlysecure.keychain.Constants;
import java.io.ByteArrayInputStream;
@@ -37,7 +38,6 @@ import java.security.cert.CertificateFactory;
import java.util.HashMap;
import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
@@ -49,15 +49,14 @@ public class TlsHelper {
}
}
- private static Map<String, byte[]> sStaticCA = new HashMap<>();
-
- public static void addStaticCA(String domain, byte[] certificate) {
- sStaticCA.put(domain, certificate);
- }
+ private static Map<String, byte[]> sPinnedCertificates = new HashMap<>();
- public static void addStaticCA(String domain, AssetManager assetManager, String name) {
+ /**
+ * Add certificate from assets to pinned certificate map.
+ */
+ public static void addPinnedCertificate(String host, AssetManager assetManager, String cerFilename) {
try {
- InputStream is = assetManager.open(name);
+ InputStream is = assetManager.open(cerFilename);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int reads = is.read();
@@ -68,27 +67,36 @@ public class TlsHelper {
is.close();
- addStaticCA(domain, baos.toByteArray());
+ sPinnedCertificates.put(host, baos.toByteArray());
} catch (IOException e) {
Log.w(Constants.TAG, e);
}
}
- public static void pinCertificateIfNecessary(OkHttpClient client, URL url) throws TlsHelperException, IOException {
+ /**
+ * Use pinned certificate for OkHttpClient if we have one.
+ *
+ * @return true, if certificate is available, false if not
+ * @throws TlsHelperException
+ * @throws IOException
+ */
+ public static boolean usePinnedCertificateIfAvailable(OkHttpClient client, URL url) throws TlsHelperException, IOException {
if (url.getProtocol().equals("https")) {
- for (String domain : sStaticCA.keySet()) {
- if (url.getHost().endsWith(domain)) {
- pinCertificate(sStaticCA.get(domain), client);
+ // use certificate PIN from assets if we have one
+ for (String host : sPinnedCertificates.keySet()) {
+ if (url.getHost().endsWith(host)) {
+ pinCertificate(sPinnedCertificates.get(host), client);
+ return true;
}
}
}
+ return false;
}
/**
* Modifies the client to accept only requests with a given certificate. Applies to all URLs requested by the
* client.
* Therefore a client that is pinned this way should be used to only make requests to URLs with passed certificate.
- * TODO: Refactor - More like SSH StrictHostKeyChecking than pinning?
*
* @param certificate certificate to pin
* @param client OkHttpClient to enforce pinning on
@@ -97,8 +105,10 @@ public class TlsHelper {
*/
private static void pinCertificate(byte[] certificate, OkHttpClient client)
throws TlsHelperException, IOException {
- // We don't use OkHttp's CertificatePinner since it depends on a TrustManager to verify it too. Refer to
- // note at end of description: http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html
+ // We don't use OkHttp's CertificatePinner since it can not be used to pin self-signed
+ // certificate if such certificate is not accepted by TrustManager.
+ // (Refer to note at end of description:
+ // http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html )
// Creating our own TrustManager that trusts only our certificate eliminates the need for certificate pinning
try {
// Load CA
@@ -126,42 +136,4 @@ public class TlsHelper {
}
}
- /**
- * Opens a Connection that will only accept certificates signed with a specific CA and skips common name check.
- * This is required for some distributed Keyserver networks like sks-keyservers.net
- *
- * @param certificate The X.509 certificate used to sign the servers certificate
- * @param url Connection target
- */
- public static HttpsURLConnection openCAConnection(byte[] certificate, URL url)
- throws TlsHelperException, IOException {
- try {
- // Load CA
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate));
-
- // Create a KeyStore containing our trusted CAs
- String keyStoreType = KeyStore.getDefaultType();
- KeyStore keyStore = KeyStore.getInstance(keyStoreType);
- keyStore.load(null, null);
- keyStore.setCertificateEntry("ca", ca);
-
- // Create a TrustManager that trusts the CAs in our KeyStore
- String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
- tmf.init(keyStore);
-
- // Create an SSLContext that uses our TrustManager
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, tmf.getTrustManagers(), null);
-
- // Tell the URLConnection to use a SocketFactory from our SSLContext
- HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
- urlConnection.setSSLSocketFactory(context.getSocketFactory());
-
- return urlConnection;
- } catch (CertificateException | KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) {
- throw new TlsHelperException(e);
- }
- }
}