Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does android get the wrong ssl certificate? (two domains, one server)

I have two domains: foo.net and bar.com. They both have SSL certificates, and they work well in all desktop and mobile browsers. They are hosted on the same server configured with nginx.

However, when I make a request to a domain from within a native android app, it somehow gets the certificate from the wrong domain! This results in an IO Exception:

request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);

...

javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>

What would cause android/java to try using the certificate from bar.com when every other measure seems to indicate that the server is correctly configured? Nothing appears in the nginx access or error log. There is no mention of bar.com anywhere in my android project.

Edit: I'm not sure why, but it appears that the server is using the certificate for bar.com for the server IP https://198.245.xx.xxx

like image 362
hughes Avatar asked Feb 22 '14 15:02

hughes


People also ask

Can you have 2 SSL certificates on one server?

A lot of people want to know whether you can install multiple SSL certificates on a single domain. The answer is yes.

How do I fix SSL certificate does not match my domain name?

If you purchased a dedicated IP address and an SSL certificate was installed immediately afterward, the domain can still be associated with the previous IP address. To solve the problem, just wait a while. As soon as the DNS records are updated, the error will disappear.

Can you use one SSL certificate multiple domains?

The simple answer is a resounding Yes! You absolutely can use one SSL certificate for multiple domains — or one SSL certificate for multiple subdomains in addition to domains.


2 Answers

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).
like image 147
Bruno Avatar answered Nov 10 '22 00:11

Bruno


A solution for Apache, more like a trick: the SSL certificates are loaded based on the vhost name from /etc/apache2/sites-enabled. So, to trick that check make sure the problematic certificate is loaded first (remember that the vhosts are loaded by name).

like image 43
Sorin Trimbitas Avatar answered Nov 09 '22 22:11

Sorin Trimbitas