package org.ovirt.mobile.movirt.rest.client.requestfactory; import android.util.Log; import org.androidannotations.annotations.AfterInject; import org.androidannotations.annotations.Bean; import org.androidannotations.annotations.EBean; import org.ovirt.mobile.movirt.auth.properties.AccountProperty; import org.ovirt.mobile.movirt.auth.properties.manager.AccountPropertiesManager; import org.ovirt.mobile.movirt.auth.properties.property.Cert; import org.ovirt.mobile.movirt.auth.properties.property.CertHandlingStrategy; import org.ovirt.mobile.movirt.rest.client.requestfactory.verifier.ListHostnameVerifier; import org.ovirt.mobile.movirt.rest.client.requestfactory.verifier.NullHostnameVerifier; import org.ovirt.mobile.movirt.util.CertHelper; import org.ovirt.mobile.movirt.util.message.ErrorType; import org.ovirt.mobile.movirt.util.message.MessageHelper; import org.springframework.http.client.SimpleClientHttpRequestFactory; import java.io.IOException; import java.net.HttpURLConnection; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; @EBean(scope = EBean.Scope.Singleton) public class OvirtSimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory { private static final String TAG = OvirtSimpleClientHttpRequestFactory.class.getSimpleName(); @Bean NullHostnameVerifier nullHostnameVerifier; @Bean ListHostnameVerifier listHostnameVerifier; @Bean MessageHelper messageHelper; @Bean AccountPropertiesManager propertiesManager; private CertHandlingStrategy certificateHandlingMode = null; @AfterInject void initFactory() { propertiesManager.notifyAndRegisterListener(new AccountProperty.CertHandlingStrategyListener() { @Override public void onPropertyChange(CertHandlingStrategy certHandlingStrategy) { onHandlingModeChange(certHandlingStrategy, null); } }); propertiesManager.registerListener(new AccountProperty.CertificateChainListener() { @Override public void onPropertyChange(Cert[] certificates) { onHandlingModeChange(certificateHandlingMode, certificates); } }); propertiesManager.notifyAndRegisterListener(new AccountProperty.ValidHostnameListListener() { @Override public void onPropertyChange(String[] validHostnameList) { listHostnameVerifier.setTrustedHosts(validHostnameList); } }); } private void onHandlingModeChange(CertHandlingStrategy certificateHandlingMode, Cert[] certChain) { this.certificateHandlingMode = certificateHandlingMode; switch (certificateHandlingMode) { case TRUST_SYSTEM: trustOnlyKnownCerts(); break; case TRUST_CUSTOM: if (certChain == null) { certChain = propertiesManager.getCertificateChain(); } trustImportedCert(certChain); break; case TRUST_ALL: trustAllHosts(); break; } } @Override protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { Log.d(TAG, "Prepare Connection"); if (connection instanceof HttpsURLConnection) { if (certificateHandlingMode == CertHandlingStrategy.TRUST_ALL) { Log.d(TAG, "trusting all certificates"); ((HttpsURLConnection) connection).setHostnameVerifier(nullHostnameVerifier); } else if (certificateHandlingMode == CertHandlingStrategy.TRUST_CUSTOM) { ((HttpsURLConnection) connection).setHostnameVerifier(listHostnameVerifier); } } super.prepareConnection(connection, httpMethod); } /** * Trust every server - dont check for any certificate */ private void trustAllHosts() { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection .setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { messageHelper.showError(e); } } private void trustImportedCert(Cert[] certChain) { try { String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); // try to add certificate - if adding fails do not trust anything Cert cert = (certChain.length == 0) ? null : certChain[certChain.length - 1]; if (cert != null) { Certificate certificate = cert.asCertificate(); if (CertHelper.isCA(certificate)) { keyStore.setCertificateEntry("ca", certificate); } } // 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(), new java.security.SecureRandom()); HttpsURLConnection .setDefaultSSLSocketFactory(context.getSocketFactory()); } catch (Exception e) { messageHelper.showError(ErrorType.NORMAL, e, "Error installing custom certificates - trusting system certificates!"); propertiesManager.setCertHandlingStrategy(CertHandlingStrategy.TRUST_SYSTEM); } } /** * This method enables certificate checking. */ private void trustOnlyKnownCerts() { try { HttpsURLConnection.setDefaultSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); } catch (Exception e) { messageHelper.showError(e); } } }