SSL connections update: notice about untrusted certificates and allow the user save...
[pub/Android/ownCloud.git] / src / com / owncloud / android / network / AdvancedX509TrustManager.java
diff --git a/src/com/owncloud/android/network/AdvancedX509TrustManager.java b/src/com/owncloud/android/network/AdvancedX509TrustManager.java
new file mode 100644 (file)
index 0000000..13a16e2
--- /dev/null
@@ -0,0 +1,117 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012 Bartek Przybylski
+ *
+ *   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 com.owncloud.android.network;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertStoreException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import android.util.Log;
+
+/**
+ * @author David A. Velasco
+ */
+public class AdvancedX509TrustManager implements X509TrustManager {
+    
+    private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
+
+    private X509TrustManager mStandardTrustManager = null;
+    private KeyStore mKnownServersKeyStore;
+
+    /**
+     * Constructor for AdvancedX509TrustManager
+     * 
+     * @param  knownServersCertStore    Local certificates store with server certificates explicitly trusted by the user.
+     * @throws CertStoreException       When no default X509TrustManager instance was found in the system.
+     */
+    public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
+            throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
+        super();
+        TrustManagerFactory factory = TrustManagerFactory
+                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        factory.init((KeyStore)null);
+        mStandardTrustManager = findX509TrustManager(factory);
+
+        mKnownServersKeyStore = knownServersKeyStore;
+    }
+    
+    
+    /**
+     * Locates the first X509TrustManager provided by a given TrustManagerFactory
+     * @param factory               TrustManagerFactory to inspect in the search for a X509TrustManager
+     * @return                      The first X509TrustManager found in factory.
+     * @throws CertStoreException   When no X509TrustManager instance was found in factory
+     */
+    private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
+        TrustManager tms[] = factory.getTrustManagers();
+        for (int i = 0; i < tms.length; i++) {
+            if (tms[i] instanceof X509TrustManager) {
+                return (X509TrustManager) tms[i];
+            }
+        }
+        return null;
+    }
+    
+
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
+     *      String authType)
+     */
+    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        mStandardTrustManager.checkClientTrusted(certificates, authType);
+    }
+
+    
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
+     *      String authType)
+     */
+    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        if (!isKnownServer(certificates[0])) {
+            Log.d(TAG, "checkClientTrusted() with standard trust manager...");
+            mStandardTrustManager.checkClientTrusted(certificates, authType);
+        }
+    }
+    
+    
+    /**
+     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+     */
+    public X509Certificate[] getAcceptedIssuers() {
+        return mStandardTrustManager.getAcceptedIssuers();
+    }
+
+    
+    private boolean isKnownServer(X509Certificate cert) {
+        try {
+            return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
+        } catch (KeyStoreException e) {
+            Log.d(TAG, "Fail while checking certificate in the known-servers store");
+            return false;
+        }
+    }
+    
+}
\ No newline at end of file