nativescript-community / https

Secure HTTP client with SSL pinning for Nativescript - iOS/Android
https://nativescript-community.github.io/https/
Other
50 stars 42 forks source link

Multiple SSL Certificate Pinning #38

Open ericgosno opened 5 years ago

ericgosno commented 5 years ago

Hello,

I am aware that from the Readme, it already said that "Once you've enabled SSL pinning you CAN NOT re-enable with a different host or certificate file." which means that for now the SSL Pinning can only work for 1 certificates.

Is there any workaround to make it works on more than 1 certificate in case we need to do SSL Pinning on more than one API endpoint?

ferryfw commented 5 years ago

Actually I got the same need in my current project. Is this feature even included somewhere in the roadmap? And for the meantime, can we work something to make it work? Anything to point us in the right direction is appreciated.

jeffwhelpley commented 5 years ago

Apologies to both of you. We are a small company and unfortunately we don't have time to update this library right now. However, we do want to resolve the outstanding issues and will get to this as soon as we can. In the meantime, if you wanted to submit a PR we would appreciate it.

@roblav96 are there any workarounds you can think of in the short term?

facetious commented 5 years ago

No Guarantees

Here's a patch that might work for you.

index a130232..0b368f1 100644
--- a/src/https.android.ts
+++ b/src/https.android.ts
@@ -27,18 +27,19 @@ interface Ipeer {
    allowInvalidCertificates: boolean
    validatesDomainName: boolean
    host?: string
-   certificate?: string
+   certificates: string[]
    x509Certificate?: java.security.cert.Certificate
 }
 let peer: Ipeer = {
    enabled: false,
    allowInvalidCertificates: false,
    validatesDomainName: true,
+   certificates: [],
 }

 export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
    // console.log('options', options)
-   if (!peer.host && !peer.certificate) {
+   if (!peer.host) {
        let certificate: string
        let inputStream: java.io.FileInputStream
        try {
@@ -58,7 +59,9 @@ export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
            return
        }
        peer.host = options.host
-       peer.certificate = certificate
+       if (peer.certificates.indexOf(certificate) === -1) {
+           peer.certificates.push(certificate)
+       }
        if (options.allowInvalidCertificates == true) {
            peer.allowInvalidCertificates = true
        }
@@ -72,6 +75,8 @@ export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
 }
 export function disableSSLPinning() {
    peer.enabled = false
+   peer.certificates.length = 0;
+   getClient(true)
    getClient(true)
    console.log('nativescript-https > Disabled SSL pinning')
 }
@@ -100,7 +105,7 @@ function getClient(reload: boolean = false): okhttp3.OkHttpClient {
            client.connectionSpecs(java.util.Collections.singletonList(spec))

            let pinner = new okhttp3.CertificatePinner.Builder()
-           pinner.add(peer.host, [peer.certificate])
+           pinner.add(peer.host, peer.certificates)
            client.certificatePinner(pinner.build())

            if (peer.allowInvalidCertificates == false) {
diff --git a/src/https.ios.ts b/src/https.ios.ts
index aed1bf9..2bb0c92 100644
--- a/src/https.ios.ts
+++ b/src/https.ios.ts
@@ -17,6 +17,7 @@ let policies: Ipolicies = {
 }
 policies.def.allowInvalidCertificates = true
 policies.def.validatesDomainName = false
+let certificates: NSData[] = [];

 export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
    // console.log('options', options)
@@ -26,12 +27,12 @@ export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
        policies.secure.allowInvalidCertificates = allowInvalidCertificates
        let validatesDomainName = (isDefined(options.validatesDomainName)) ? options.validatesDomainName : true
        policies.secure.validatesDomainName = validatesDomainName
-       let data = NSData.dataWithContentsOfFile(options.certificate)
+       certificates.push(NSData.dataWithContentsOfFile(options.certificate))
        // console.log('data.description', data.description)
        // console.log('data.bytes', data.bytes)
        // console.log('data.base64Encoding()', data.base64Encoding())
        // console.log('data.length', data.length)
-       policies.secure.pinnedCertificates = NSSet.setWithObject(data)
+       policies.secure.pinnedCertificates = NSSet.setWithArray(certificates)
    }
    policies.secured = true
    console.log('nativescript-https > Enabled SSL pinning')
adambeck7 commented 4 years ago

Was there ever an official fix for this? Has anyone gotten the above patch to work?