Merge "Use SSLCertificateSocketFactory to generate "insecure" ssl socket."
diff --git a/src/com/android/email/mail/store/TrustManagerFactory.java b/src/com/android/email/mail/store/TrustManagerFactory.java
deleted file mode 100644
index 7f07845..0000000
--- a/src/com/android/email/mail/store/TrustManagerFactory.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.mail.store;
-
-import com.android.common.DomainNameValidator;
-import com.android.email.Email;
-
-import org.apache.harmony.xnet.provider.jsse.SSLParameters;
-
-import android.util.Log;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.X509TrustManager;
-
-/**
- * This factory creates and returns two types of TrustManagers.
- *
- * The "secure" trust manager performs standard tests of certificates, and throws
- * CertificateException when the tests fail.
- *
- * The "simple" trust manager performs no tests, effectively accepting all certificates.
- */
-public final class TrustManagerFactory {
-    private static X509TrustManager sUnsecureTrustManager = new SimpleX509TrustManager();
-
-    /**
-     * This trust manager performs no tests, effectively accepting all certificates.
-     */
-    private static class SimpleX509TrustManager implements X509TrustManager {
-        public void checkClientTrusted(X509Certificate[] chain, String authType) {
-            logCertificates(chain, "Trusting client", false);
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain, String authType) {
-            logCertificates(chain, "Trusting server", false);
-        }
-
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
-    }
-
-    /**
-     * This trust manager performs full tests, requiring a valid, trusted certificate.
-     */
-    private static class SecureX509TrustManager implements X509TrustManager {
-        private X509TrustManager mTrustManager;
-        private String mHost;
-
-        SecureX509TrustManager(X509TrustManager trustManager, String host) {
-            mTrustManager = trustManager;
-            mHost = host;
-        }
-
-        public void checkClientTrusted(X509Certificate[] chain, String authType)
-                throws CertificateException {
-            try {
-                mTrustManager.checkClientTrusted(chain, authType);
-            } catch (CertificateException ce) {
-                logCertificates(chain, "Failed client", true);
-                throw ce;
-            }
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain, String authType)
-                throws CertificateException {
-
-            try {
-                mTrustManager.checkServerTrusted(chain, authType);
-            } catch (CertificateException ce) {
-                logCertificates(chain, "Failed server", true);
-                throw ce;
-            }
-
-            if (!DomainNameValidator.match(chain[0], mHost)) {
-                logCertificates(chain, "Failed domain name", true);
-                throw new CertificateException("Certificate domain name does not match " + mHost);
-            }
-        }
-
-        public X509Certificate[] getAcceptedIssuers() {
-            return mTrustManager.getAcceptedIssuers();
-        }
-    }
-
-    /**
-     * Logging of certificates, to help debugging trust issues.  Logging strategy:
-     *   Trusting a certificate:  Lightweight log about it
-     *   Fully checking:  Silent if OK, verbose log it failure
-     *
-     * @param chain the certificate chain to dump
-     * @param caller a prefix that will be added to each log
-     * @param verbose if true, the issuer and dates will also be logged
-     */
-    private static void logCertificates(X509Certificate[] chain, String caller, boolean verbose) {
-        if (Email.DEBUG) {
-            for (int i = 0; i < chain.length; ++i) {
-                Log.d(Email.LOG_TAG, caller + " Certificate #" + i);
-                Log.d(Email.LOG_TAG, "  subject=" + chain[i].getSubjectDN());
-                if (verbose) {
-                    Log.d(Email.LOG_TAG, "  issuer=" + chain[i].getIssuerDN());
-                    Log.d(Email.LOG_TAG, "  dates=" + chain[i].getNotBefore()
-                            + " to " + chain[i].getNotAfter());
-                }
-            }
-        }
-    }
-
-    private TrustManagerFactory() {
-    }
-
-    public static X509TrustManager get(String host, boolean secure) {
-        if (secure) {
-            return new SecureX509TrustManager(SSLParameters.getDefaultTrustManager(), host) ;
-        } else {
-            return sUnsecureTrustManager;
-        }
-    }
-}
diff --git a/src/com/android/email/mail/transport/MailTransport.java b/src/com/android/email/mail/transport/MailTransport.java
index bdfc7bb..a42bd24 100644
--- a/src/com/android/email/mail/transport/MailTransport.java
+++ b/src/com/android/email/mail/transport/MailTransport.java
@@ -20,7 +20,6 @@
 import com.android.email.mail.CertificateValidationException;
 import com.android.email.mail.MessagingException;
 import com.android.email.mail.Transport;
-import com.android.email.mail.store.TrustManagerFactory;
 
 import android.util.Config;
 import android.util.Log;
@@ -153,11 +152,7 @@
         try {
             SocketAddress socketAddress = new InetSocketAddress(getHost(), getPort());
             if (canTrySslSecurity()) {
-                SSLContext sslContext = SSLContext.getInstance("TLS");
-                sslContext.init(null, new TrustManager[] {
-                        TrustManagerFactory.get(getHost(), !canTrustAllCertificates())
-                }, new SecureRandom());
-                mSocket = sslContext.getSocketFactory().createSocket();
+                mSocket = SSLUtils.getSSLSocketFactory(canTrustAllCertificates()).createSocket();
             } else {
                 mSocket = new Socket();
             }
@@ -170,11 +165,6 @@
                 Log.d(Email.LOG_TAG, e.toString());
             }
             throw new CertificateValidationException(e.getMessage(), e);
-        } catch (GeneralSecurityException gse) {
-            if (Config.LOGD && Email.DEBUG) {
-                Log.d(Email.LOG_TAG, gse.toString());
-            }
-            throw new MessagingException(MessagingException.GENERAL_SECURITY, gse.toString());
         } catch (IOException ioe) {
             if (Config.LOGD && Email.DEBUG) {
                 Log.d(Email.LOG_TAG, ioe.toString());
@@ -190,12 +180,8 @@
      */
     public void reopenTls() throws MessagingException {
         try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, new TrustManager[] {
-                    TrustManagerFactory.get(getHost(), !canTrustAllCertificates())
-            }, new SecureRandom());
-            mSocket = sslContext.getSocketFactory().createSocket(mSocket, getHost(), getPort(),
-                    true);
+            mSocket = SSLUtils.getSSLSocketFactory(canTrustAllCertificates())
+                    .createSocket(mSocket, getHost(), getPort(), true);
             mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
             mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
             mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
@@ -205,11 +191,6 @@
                 Log.d(Email.LOG_TAG, e.toString());
             }
             throw new CertificateValidationException(e.getMessage(), e);
-        } catch (GeneralSecurityException gse) {
-            if (Config.LOGD && Email.DEBUG) {
-                Log.d(Email.LOG_TAG, gse.toString());
-            }
-            throw new MessagingException(MessagingException.GENERAL_SECURITY, gse.toString());
         } catch (IOException ioe) {
             if (Config.LOGD && Email.DEBUG) {
                 Log.d(Email.LOG_TAG, ioe.toString());
diff --git a/src/com/android/email/mail/transport/SSLUtils.java b/src/com/android/email/mail/transport/SSLUtils.java
new file mode 100644
index 0000000..499a8b1
--- /dev/null
+++ b/src/com/android/email/mail/transport/SSLUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.email.mail.transport;
+
+import android.net.SSLCertificateSocketFactory;
+
+import javax.net.ssl.SSLSocketFactory;
+
+public class SSLUtils {
+    private static SSLSocketFactory sInsecureFactory;
+    private static SSLSocketFactory sSecureFactory;
+
+    /**
+     * Returns a {@link SSLSocketFactory}.  Optionally bypass all SSL certificate checks.
+     *
+     * @param insecure if true, bypass all SSL certificate checks
+     */
+    public synchronized static final SSLSocketFactory getSSLSocketFactory(boolean insecure) {
+        if (insecure) {
+            if (sInsecureFactory == null) {
+                sInsecureFactory = SSLCertificateSocketFactory.getInsecure(0, null);
+            }
+            return sInsecureFactory;
+        } else {
+            if (sSecureFactory == null) {
+                sSecureFactory = SSLCertificateSocketFactory.getDefault(0, null);
+            }
+            return sSecureFactory;
+        }
+    }
+}
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java
index 74d93a1..d2e7121 100644
--- a/src/com/android/exchange/SyncManager.java
+++ b/src/com/android/exchange/SyncManager.java
@@ -21,7 +21,7 @@
 import com.android.email.Email;
 import com.android.email.SecurityPolicy;
 import com.android.email.mail.MessagingException;
-import com.android.email.mail.store.TrustManagerFactory;
+import com.android.email.mail.transport.SSLUtils;
 import com.android.email.provider.EmailContent;
 import com.android.email.provider.EmailContent.Account;
 import com.android.email.provider.EmailContent.Attachment;
@@ -1054,30 +1054,16 @@
                     PlainSocketFactory.getSocketFactory(), 80));
             registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
 
-            // Create a new SSLSocketFactory for our "trusted ssl"
-            // Get the unsecure trust manager from the factory
-            X509TrustManager trustManager = TrustManagerFactory.get(null, false);
-            TrustManager[] trustManagers = new TrustManager[] {trustManager};
-            SSLContext sslcontext;
-            try {
-                sslcontext = SSLContext.getInstance("TLS");
-                try {
-                    sslcontext.init(null, trustManagers, null);
-                } catch (KeyManagementException e) {
-                    throw new AssertionError(e);
-                }
-                // Ok, now make our factory
-                SSLSocketFactory sf = new SSLSocketFactory(sslcontext.getSocketFactory());
-                sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-                // Register the httpts scheme with our factory
-                registry.register(new Scheme("httpts", sf, 443));
-                // And create a ccm with our registry
-                HttpParams params = new BasicHttpParams();
-                params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 25);
-                params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, sConnPerRoute);
-                sClientConnectionManager = new ThreadSafeClientConnManager(params, registry);
-            } catch (NoSuchAlgorithmException e2) {
-            }
+            // Use "insecure" socket factory.
+            SSLSocketFactory sf = new SSLSocketFactory(SSLUtils.getSSLSocketFactory(true));
+            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            // Register the httpts scheme with our factory
+            registry.register(new Scheme("httpts", sf, 443));
+            // And create a ccm with our registry
+            HttpParams params = new BasicHttpParams();
+            params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 25);
+            params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, sConnPerRoute);
+            sClientConnectionManager = new ThreadSafeClientConnManager(params, registry);
         }
         // Null is a valid return result if we get an exception
         return sClientConnectionManager;