diff --git a/CHANGELOG.md b/CHANGELOG.md index eccc971..a34862f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 2.0.3 + +- Fixed #172: plugin does not respect user installed CA certs on Android + +#### Important information +We've changed a default behavior on Android. User installed CA certs are respected now. +If you don't want this for your needs, you can switch back to old behavior by setting SSL cert mode to `legacy`. + ## 2.0.2 - Fixed #142: Plugin affected by REDoS Issue of tough-cookie diff --git a/README.md b/README.md index 4de62bc..83a31ca 100644 --- a/README.md +++ b/README.md @@ -132,12 +132,13 @@ These functions all take success and error callbacks as their last 2 arguments. Set SSL Cert handling mode, being one of the following values: * `default`: default SSL cert handling using system's CA certs +* `legacy`: use legacy default behavior (< 2.0.3), excluding user installed CA certs (only for Android) * `nocheck`: disable SSL cert checking, trusting all certs (meant to be used only for testing purposes) * `pinned`: trust only provided certs To use SSL pinning you must include at least one `.cer` SSL certificate in your app project. You can pin to your server certificate or to one of the issuing CA certificates. Include your certificate in the `www/certificates` folder. All `.cer` files found there will be loaded automatically. -:warning: Your certificate must be DER encoded! If you only have a PEM enoceded certificate see this [stackoverflow answer](http://stackoverflow.com/a/16583429/3182729). You want to convert it to a DER encoded certificate with a .cer extension. +:warning: Your certificate must be DER encoded! If you only have a PEM encoded certificate read this [stackoverflow answer](http://stackoverflow.com/a/16583429/3182729). You want to convert it to a DER encoded certificate with a .cer extension. ```js // enable SSL pinning diff --git a/package.json b/package.json index ad246a9..48d476b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-advanced-http", - "version": "2.0.2", + "version": "2.0.3", "description": "Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning", "scripts": { "updatecert": "node ./scripts/update-test-cert.js", diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPlugin.java b/src/android/com/synconset/cordovahttp/CordovaHttpPlugin.java index df16753..bcf9b65 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpPlugin.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpPlugin.java @@ -8,8 +8,11 @@ import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; import java.util.ArrayList; +import java.util.Enumeration; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; @@ -89,7 +92,7 @@ public class CordovaHttpPlugin extends CordovaPlugin { } else if (action.equals("setSSLCertMode")) { String mode = args.getString(0); - if (mode.equals("default")) { + if (mode.equals("legacy")) { HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_DEFAULT); callbackContext.success(); } else if (mode.equals("nocheck")) { @@ -100,10 +103,19 @@ public class CordovaHttpPlugin extends CordovaPlugin { this.loadSSLCerts(); HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_PINNED); callbackContext.success(); - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); callbackContext.error("There was an error setting up ssl pinning"); } + } else if (mode.equals("default")) { + try { + this.loadUserStoreSSLCerts(); + HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_PINNED); + callbackContext.success(); + } catch (Exception e) { + e.printStackTrace(); + callbackContext.error("There was an error loading system's CA certificates"); + } } } else if (action.equals("uploadFile")) { String urlString = args.getString(0); @@ -134,6 +146,16 @@ public class CordovaHttpPlugin extends CordovaPlugin { return true; } + private void loadUserStoreSSLCerts() throws Exception { + KeyStore ks = KeyStore.getInstance("AndroidCAStore"); + ks.load(null); + Enumeration aliases = ks.aliases(); + + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + } + } + private void loadSSLCerts() throws GeneralSecurityException, IOException { AssetManager assetManager = cordova.getActivity().getAssets(); String[] files = assetManager.list("www/certificates"); diff --git a/src/ios/CordovaHttpPlugin.m b/src/ios/CordovaHttpPlugin.m index 15fa17f..4047057 100644 --- a/src/ios/CordovaHttpPlugin.m +++ b/src/ios/CordovaHttpPlugin.m @@ -124,7 +124,7 @@ - (void)setSSLCertMode:(CDVInvokedUrlCommand*)command { NSString *certMode = [command.arguments objectAtIndex:0]; - if ([certMode isEqualToString: @"default"]) { + if ([certMode isEqualToString: @"default"] || [certMode isEqualToString: @"legacy"]) { securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; securityPolicy.allowInvalidCertificates = NO; securityPolicy.validatesDomainName = YES; diff --git a/www/helpers.js b/www/helpers.js index 4d636b2..87a564d 100644 --- a/www/helpers.js +++ b/www/helpers.js @@ -3,7 +3,7 @@ var cookieHandler = require(pluginId + '.cookie-handler'); var messages = require(pluginId + '.messages'); var validSerializers = [ 'urlencoded', 'json', 'utf8' ]; -var validCertModes = [ 'default', 'nocheck', 'pinned' ]; +var validCertModes = [ 'default', 'nocheck', 'pinned', 'legacy' ]; var validHttpMethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download' ]; module.exports = {