From 0b181743a3d6b1423e112b17a400b5ac4ac09bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 20 Sep 2015 22:42:50 +0200 Subject: Keyservers: Dont follow redirects, pin pgp.mit.edu, check for pinned cert on add (OKC-01-018) --- .../keychain/util/TlsHelper.java | 82 +++++++--------------- 1 file changed, 27 insertions(+), 55 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java') 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 + * Copyright (C) 2013-2015 Dominik Schürmann * * 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 sStaticCA = new HashMap<>(); - - public static void addStaticCA(String domain, byte[] certificate) { - sStaticCA.put(domain, certificate); - } + private static Map 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); - } - } } -- cgit v1.2.3