As mentioned in the previous post I access my Azure-hosted service from Android over HTTPS. This worked just fine on my Android 4.1 phone, but when I tested on a version 2.2 emulator I received an error:
javax.net.ssl.SSLException: Not trusted server certificate at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371) ~[na:0.0] at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168) ~[na:0.0] ... Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found. at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168) ~[na:0.0] at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366) ~[na:0.0] ... 5 common frames omitted Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found. at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:149) ~[na:0.0] at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202) ~[na:0.0] at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164) ~[na:0.0] ... 6 common frames omitted
This happens because Android 2.2 (and presumably lower versions too) does not accept the Azure SSL certificate.
The really simple solution is to just ignore 2.2: according to the Android Dashboards 2.2 now accounts for only 0.7% of the install base (and shrinking). However, the rest of the app works fine (mainly due to the Android Support Library) and so I wanted to fix this if possible.
The *bad* solution
We can just trust all certificates and that will fix it, right? Well, yes, but you're opening yourself (well, the user) up to man in the middle attacks - if someone can insert themself between the user and the server, returning a valid (and now trusted) certificate, they can intercept all the encrypted HTTPS traffic.
I'm not even going to post sample code for this.
Don't do it.
The correct solution
What we want to do is just trust our known Azure certificate.
The way we do this is to create a KeyStore containing our certificate, and then use that to create a SSLSocketFactory, which the client then uses when it needs to create the connection to our server.
I hope the 0.7% of my users are happy :)