got ssl pinning to work when hardcoded

This commit is contained in:
Andrew Stephan 2014-03-24 19:36:09 -04:00
parent b81f8b3d41
commit b65be932bd
4 changed files with 92 additions and 20 deletions

View File

@ -3,8 +3,22 @@
*/ */
package com.synconset; package com.synconset;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Iterator; import java.util.Iterator;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaPlugin;
@ -18,12 +32,14 @@ import android.util.Base64;
public class CordovaHTTP extends CordovaPlugin { public class CordovaHTTP extends CordovaPlugin {
private static final String TAG = "CordovaHTTP"; private static final String TAG = "CordovaHTTP";
private SSLContext sslContext;
private JSONObject globalHeaders; private JSONObject globalHeaders;
@Override @Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) { public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView); super.initialize(cordova, webView);
this.globalHeaders = new JSONObject(); this.globalHeaders = new JSONObject();
this.sslContext = null;
} }
@Override @Override
@ -33,22 +49,28 @@ public class CordovaHTTP extends CordovaPlugin {
JSONObject params = args.getJSONObject(1); JSONObject params = args.getJSONObject(1);
JSONObject headers = args.getJSONObject(2); JSONObject headers = args.getJSONObject(2);
this.addToJSONObject(headers, this.globalHeaders); this.addToJSONObject(headers, this.globalHeaders);
HTTPGet get = new HTTPGet(urlString, params, headers, callbackContext); HTTPGet get = new HTTPGet(urlString, params, headers, this.sslContext, callbackContext);
cordova.getThreadPool().execute(get); cordova.getThreadPool().execute(get);
} else if (action.equals("post")) { } else if (action.equals("post")) {
String urlString = args.getString(0); String urlString = args.getString(0);
JSONObject params = args.getJSONObject(1); JSONObject params = args.getJSONObject(1);
JSONObject headers = args.getJSONObject(2); JSONObject headers = args.getJSONObject(2);
this.addToJSONObject(headers, this.globalHeaders); this.addToJSONObject(headers, this.globalHeaders);
HTTPPost post = new HTTPPost(urlString, params, headers, callbackContext); HTTPPost post = new HTTPPost(urlString, params, headers, this.sslContext, callbackContext);
cordova.getThreadPool().execute(post); cordova.getThreadPool().execute(post);
} else if (action.equals("setAuthorizationHeaderWithUsernameAndPassword")) { } else if (action.equals("setAuthorizationHeaderWithUsernameAndPassword")) {
String username = args.getString(0); String username = args.getString(0);
String password = args.getString(1); String password = args.getString(1);
this.setAuthorizationHeaderWithUsernameAndPassword(username, password); this.setAuthorizationHeaderWithUsernameAndPassword(username, password);
callbackContext.success(); callbackContext.success();
} else if (action.equals("downloadFile")) { } else if (action.equals("setSSLPinningMode")) {
int mode = args.getInt(0);
try {
this.setSSLPinningMode(mode);
callbackContext.success();
} catch(Exception e) {
callbackContext.error("There was an error setting up ssl pinning");
}
} else { } else {
return false; return false;
} }
@ -61,6 +83,37 @@ public class CordovaHTTP extends CordovaPlugin {
globalHeaders.put("Authorization", loginInfo); globalHeaders.put("Authorization", loginInfo);
} }
private void setSSLPinningMode(int mode) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream in = cordova.getActivity().getAssets().open("PCA-3G5.cer");
InputStream caInput = new BufferedInputStream(in);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// 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 = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
}
private void addToJSONObject(JSONObject object, JSONObject objectToAdd) throws JSONException { private void addToJSONObject(JSONObject object, JSONObject objectToAdd) throws JSONException {
Iterator<?> i = objectToAdd.keys(); Iterator<?> i = objectToAdd.keys();

View File

@ -15,6 +15,8 @@ import java.io.BufferedReader;
import java.net.URLConnection; import java.net.URLConnection;
import javax.net.ssl.SSLContext;
import java.util.Iterator; import java.util.Iterator;
import android.util.Log; import android.util.Log;
@ -27,12 +29,14 @@ public class HTTP {
private String urlString; private String urlString;
private JSONObject params; private JSONObject params;
private JSONObject headers; private JSONObject headers;
private SSLContext sslContext;
private CallbackContext callbackContext; private CallbackContext callbackContext;
public HTTP(String urlString, JSONObject params, JSONObject headers, CallbackContext callbackContext) { public HTTP(String urlString, JSONObject params, JSONObject headers, SSLContext sslContext, CallbackContext callbackContext) {
this.urlString = urlString; this.urlString = urlString;
this.params = params; this.params = params;
this.headers = headers; this.headers = headers;
this.sslContext = sslContext;
this.callbackContext = callbackContext; this.callbackContext = callbackContext;
} }
@ -60,6 +64,10 @@ public class HTTP {
this.headers = headers; this.headers = headers;
} }
protected SSLContext getSSLContext() {
return this.sslContext;
}
protected CallbackContext getCallbackContext() { protected CallbackContext getCallbackContext() {
return this.callbackContext; return this.callbackContext;
} }

View File

@ -9,6 +9,7 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.json.JSONException; import org.json.JSONException;
@ -17,8 +18,8 @@ import org.json.JSONObject;
import android.util.Log; import android.util.Log;
public class HTTPGet extends HTTP implements Runnable { public class HTTPGet extends HTTP implements Runnable {
public HTTPGet(String urlString, JSONObject params, JSONObject headers, CallbackContext callbackContext) { public HTTPGet(String urlString, JSONObject params, JSONObject headers, SSLContext sslContext, CallbackContext callbackContext) {
super(urlString, params, headers, callbackContext); super(urlString, params, headers, sslContext, callbackContext);
} }
@Override @Override
@ -26,15 +27,14 @@ public class HTTPGet extends HTTP implements Runnable {
JSONObject params = this.getParams(); JSONObject params = this.getParams();
String urlString = this.getUrlString(); String urlString = this.getUrlString();
CallbackContext callbackContext = this.getCallbackContext(); CallbackContext callbackContext = this.getCallbackContext();
JSONObject response = new JSONObject();
InputStream is = null; InputStream is = null;
HttpsURLConnection conn = null; HttpsURLConnection conn = null;
try { try {
if (params.length() > 0) { if (params.length() > 0) {
urlString = urlString + "?" + this.getQueryString(); urlString = urlString + "?" + this.getQueryString();
} }
URL url = new URL(urlString); URL url = new URL(urlString);
conn = (HttpsURLConnection)url.openConnection(); conn = (HttpsURLConnection)url.openConnection();
conn.setRequestMethod("GET"); conn.setRequestMethod("GET");
conn.setDoInput(true); conn.setDoInput(true);
@ -42,14 +42,23 @@ public class HTTPGet extends HTTP implements Runnable {
this.addHeaders(conn); this.addHeaders(conn);
conn.connect(); conn.connect();
int status = conn.getResponseCode(); int status = conn.getResponseCode();
Log.d(TAG, "The response is: " + status); if (status >= 200 && status < 300) {
is = conn.getInputStream(); is = conn.getInputStream();
String responseData = this.readInputStream(is); String responseData = this.readInputStream(is);
response.put("status", status); JSONObject response = new JSONObject();
response.put("data", responseData); response.put("status", status);
callbackContext.success(response); response.put("data", responseData);
callbackContext.success(response);
} else {
is = conn.getErrorStream();
String responseData = this.readInputStream(is);
JSONObject response = new JSONObject();
response.put("status", status);
response.put("error", responseData);
callbackContext.error(response);
}
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
this.respondWithError(callbackContext, "There is an error with the url"); this.respondWithError(callbackContext, "There is an error with the url");
} catch (JSONException e) { } catch (JSONException e) {
this.respondWithError(callbackContext, "There was an error with the params, headers or generating the response"); this.respondWithError(callbackContext, "There was an error with the params, headers or generating the response");
} catch (IOException e) { } catch (IOException e) {

View File

@ -12,6 +12,7 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.json.JSONException; import org.json.JSONException;
@ -20,8 +21,8 @@ import org.json.JSONObject;
import android.util.Log; import android.util.Log;
public class HTTPPost extends HTTP implements Runnable { public class HTTPPost extends HTTP implements Runnable {
public HTTPPost(String urlString, JSONObject params, JSONObject headers, CallbackContext callbackContext) { public HTTPPost(String urlString, JSONObject params, JSONObject headers, SSLContext sslContext, CallbackContext callbackContext) {
super(urlString, params, headers, callbackContext); super(urlString, params, headers, sslContext, callbackContext);
} }
@Override @Override
@ -34,6 +35,7 @@ public class HTTPPost extends HTTP implements Runnable {
try { try {
URL url = new URL(urlString); URL url = new URL(urlString);
conn = (HttpsURLConnection)url.openConnection(); conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(this.getSSLContext().getSocketFactory());
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setDoInput(true); conn.setDoInput(true);
conn.setDoOutput(true); conn.setDoOutput(true);
@ -50,7 +52,6 @@ public class HTTPPost extends HTTP implements Runnable {
conn.connect(); conn.connect();
int status = conn.getResponseCode(); int status = conn.getResponseCode();
Log.d(TAG, "The response is: " + status);
if (status >= 200 && status < 300) { if (status >= 200 && status < 300) {
is = conn.getInputStream(); is = conn.getInputStream();
String responseData = this.readInputStream(is); String responseData = this.readInputStream(is);
@ -71,6 +72,7 @@ public class HTTPPost extends HTTP implements Runnable {
} catch (JSONException e) { } catch (JSONException e) {
this.respondWithError(callbackContext, "There was an error with the params, headers or generating the response"); this.respondWithError(callbackContext, "There was an error with the params, headers or generating the response");
} catch (IOException e) { } catch (IOException e) {
Log.d(TAG, e.getMessage());
this.respondWithError(callbackContext, "There was an error with the request"); this.respondWithError(callbackContext, "There was an error with the request");
} finally { } finally {
if (is != null) { if (is != null) {