Dealing with the above mentioned Exception has sent me into a wild-goose chase for a quick fix.
Unfortunately the depth of this problem is much larger than I anticipated.
A quick web search suggests that there is a problem with the SSL chain, therefore this would mean that there is a SSL configuration problem on the server, that it's not serving the certificates correctly, eg. in the correct order, or using a self-signed certificate in which case the server also acts as the Certificate Authority.
Some mentioned solutions were to implement your own SSL Client, with a Trust Manager that does absolutely nothing. This is
VERY VERY BAD. Don't do it.
Other suggestions were to use your own Trust Keystore (when using self signed certificates, or using "untrusted CAs", like, for example, a university CA).
But if you're using a trusted CA this shouldn't be a problem, right?
For a SSL Server Test you can use Qualys' tool here:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
Using this test I found no errors on the domain, but there was a notice that the site
only works in browsers with SNI support.
SNI (Server Name Indication) is kind of like a Virtual Host for SSL. Usually SSL certificates were issued for an IP address, but having multiple virtual hosts on the same server can cause problems like
different browsers getting different SSL certificates from the same server.
You can test this if you have Android <= 2.3.7. Open the browser and navigate to the site. If you get a certificate warning, check the certificate.
So, obviously, if old browsers have this problems, there are going to be problems in the code too.
The answer here summarizes it. The best workaround seems to be to use another library, which supports SNI.
http://stackoverflow.com/questions/21956663/why-does-android-get-the-wrong-ssl-certificate-two-domains-one-server
The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).
You're also visibly using the Apache HTTP Client library (not HttpsURLConnection
, for which there can be SNI support with some Android versions. Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).
Another two options would be:
- to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
- to use another HTTP Client library (e.g.
HttpsURLConnection
).
Other notes:
Installing the INTERMEDIATE certificate into Apache on Ubuntu/Debian systems
Credits:
https://gist.github.com/mgedmin/7124635
SSLCertificateFile /etc/ssl/certs/subdomain.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/subdomain.example.com.pem
SSLCertificateChainFile /etc/ssl/certs/startssl-class1-intermediate.crt