From 755591f9e53639ef7d63799ded6ef827a5e03ebd Mon Sep 17 00:00:00 2001 From: Andrew Young Date: Wed, 8 Jan 2014 14:30:10 -0800 Subject: [PATCH 1/3] Updates the android target to use a version of HttpClient that is closer to the version shipped with Android. Also adds support for skipping SSL certificate verifcation. This allows the client to be used with self signed certificates. Conflicts: src/main/resources/android-java/apiInvoker.mustache --- .../android-java/apiInvoker.mustache | 98 ++++++++++++++++++- src/main/resources/android-java/pom.mustache | 2 +- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/main/resources/android-java/apiInvoker.mustache b/src/main/resources/android-java/apiInvoker.mustache index 453adb690d0..cd4aa5498a4 100644 --- a/src/main/resources/android-java/apiInvoker.mustache +++ b/src/main/resources/android-java/apiInvoker.mustache @@ -9,11 +9,18 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.apache.http.*; import org.apache.http.client.*; import org.apache.http.client.methods.*; +import org.apache.http.conn.*; +import org.apache.http.conn.scheme.*; +import org.apache.http.conn.ssl.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.*; +import org.apache.http.impl.conn.*; +import org.apache.http.params.*; import org.apache.http.util.EntityUtils; import java.io.File; +import java.net.Socket; +import java.net.UnknownHostException; import java.net.URLEncoder; import java.util.Map; @@ -22,15 +29,50 @@ import java.util.List; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.*; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import java.util.Date; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + public class ApiInvoker { private static ApiInvoker INSTANCE = new ApiInvoker(); private Map defaultHeaderMap = new HashMap(); private HttpClient client = null; + + private boolean ignoreSSLCertificates = false; + + private ClientConnectionManager ignoreSSLConnectionManager; + + public ApiInvoker() { + initConnectionManager(); + } + public static ApiInvoker getInstance() { return INSTANCE; } + public void ignoreSSLCertificates(boolean ignoreSSLCertificates) { + this.ignoreSSLCertificates = ignoreSSLCertificates; + } + public void addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); } @@ -167,8 +209,58 @@ public class ApiInvoker { } private HttpClient getClient(String host) { - if(client == null) - client = new DefaultHttpClient(); + if(client == null) { + if (ignoreSSLCertificates && ignoreSSLConnectionManager != null) { + // Trust self signed certificates + client = new DefaultHttpClient(ignoreSSLConnectionManager, new BasicHttpParams()); + } else { + client = new DefaultHttpClient(); + } + } return client; } -} \ No newline at end of file + + private void initConnectionManager() { + try { + final SSLContext sslContext = SSLContext.getInstance("SSL"); + + // set up a TrustManager that trusts everything + TrustManager[] trustManagers = new TrustManager[] { + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + }}; + + sslContext.init(null, trustManagers, new SecureRandom()); + + SSLSocketFactory sf = new SSLSocketFactory((KeyStore)null) { + private javax.net.ssl.SSLSocketFactory sslFactory = sslContext.getSocketFactory(); + + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) + throws IOException, UnknownHostException { + return sslFactory.createSocket(socket, host, port, autoClose); + } + + public Socket createSocket() throws IOException { + return sslFactory.createSocket(); + } + }; + + sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + Scheme httpsScheme = new Scheme("https", sf, 443); + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(httpsScheme); + + ignoreSSLConnectionManager = new SingleClientConnManager(new BasicHttpParams(), schemeRegistry); + } catch (NoSuchAlgorithmException e) { + // This will only be thrown if SSL isn't available for some reason. + } catch (KeyManagementException e) { + // This might be thrown when passing a key into init(), but no key is being passed. + } catch (GeneralSecurityException e) { + throw new RuntimeException("Couldn't Init SSLSocketFactory: " + e.getMessage(), e); + } + } +} diff --git a/src/main/resources/android-java/pom.mustache b/src/main/resources/android-java/pom.mustache index 5ec4fd76a82..abfe1ce3a1f 100644 --- a/src/main/resources/android-java/pom.mustache +++ b/src/main/resources/android-java/pom.mustache @@ -207,7 +207,7 @@ 1.0.0 4.8.1 1.6.1 - 4.2.3 + 4.0 3.1.5 From f8807c7440efb8c29362d48af17d82484ee1a364 Mon Sep 17 00:00:00 2001 From: Andrew Young Date: Wed, 8 Jan 2014 15:21:55 -0800 Subject: [PATCH 2/3] Code cleanup. --- src/main/resources/android-java/apiInvoker.mustache | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/android-java/apiInvoker.mustache b/src/main/resources/android-java/apiInvoker.mustache index cd4aa5498a4..81696c572d0 100644 --- a/src/main/resources/android-java/apiInvoker.mustache +++ b/src/main/resources/android-java/apiInvoker.mustache @@ -209,7 +209,7 @@ public class ApiInvoker { } private HttpClient getClient(String host) { - if(client == null) { + if (client == null) { if (ignoreSSLCertificates && ignoreSSLConnectionManager != null) { // Trust self signed certificates client = new DefaultHttpClient(ignoreSSLConnectionManager, new BasicHttpParams()); @@ -260,7 +260,8 @@ public class ApiInvoker { } catch (KeyManagementException e) { // This might be thrown when passing a key into init(), but no key is being passed. } catch (GeneralSecurityException e) { - throw new RuntimeException("Couldn't Init SSLSocketFactory: " + e.getMessage(), e); + // This catches anything else that might go wrong. + // If anything goes wrong we default to the standard connection manager. } } } From 52905fd6deb6d30d8a60ad4ae21c7e0efc202aca Mon Sep 17 00:00:00 2001 From: Andrew Young Date: Wed, 8 Jan 2014 16:24:17 -0800 Subject: [PATCH 3/3] Adds http scheme back in. --- src/main/resources/android-java/apiInvoker.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/android-java/apiInvoker.mustache b/src/main/resources/android-java/apiInvoker.mustache index 81696c572d0..282e1c12da8 100644 --- a/src/main/resources/android-java/apiInvoker.mustache +++ b/src/main/resources/android-java/apiInvoker.mustache @@ -253,6 +253,7 @@ public class ApiInvoker { Scheme httpsScheme = new Scheme("https", sf, 443); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); + schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); ignoreSSLConnectionManager = new SingleClientConnManager(new BasicHttpParams(), schemeRegistry); } catch (NoSuchAlgorithmException e) {