1

While accessing our own website in Java code, an exception is thrown:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching en.greatfire.org found.

However, when accessing it in a browser or using curl, there's no problem.

Any idea why this could be? If there's any problem with our certificates but browsers are somehow more lenient we'd like to fix it.

Not sure if it's related, we have separate certificates for greatfire.org and en.greatfire.org.

Java code that throws the above exception:

    URL url = new URL("https://en.greatfire.org");
    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
    System.out.println("Response code: " + conn.getResponseCode());
    for(Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
        for(String headerValue : header.getValue()) {
            System.out.println(header.getKey() + ": " + headerValue);
        }
    }
Vikram
  • 8,235
  • 33
  • 47
GreatFire
  • 427
  • 1
  • 5
  • 11

1 Answers1

3

RFC 2818 (the HTTPS specification) says:

If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.

Essentially, if there's in no SAN extension at all, it should use the CN in the Subject DN, otherwise, it should only use the SAN entries. (The more recent RFC 6125 also goes along these lines.)

It sounds like your certificate has one or more SAN entries, but none of them are valid for the host name you're after (which could be in the CN only).

Java is quite strict on this, including on the type of SAN entry (e.g. for IP addresses), but some browsers are more lenient. I'd suggest fixing the certificate by putting all the host names (or IP addresses) you want to use in Subject Alternative Names.

EDIT:

This being said, you have a couple of related problems.

The certificate you serve for en.greatfire.org has SAN entries for both en.greatfire.org and www.en.greatfire.org, which is fine and should work.

However, if you're using a client that doesn't support the SSL/TLS Server Name Indication extension (e.g. openssl s_client -showcerts -connect en.greatfire.org:443, or Java 6 for that matter), you get a certificate for greatfire.org and www.greatfire.org.

This is a double problem because:

  • You've configured SNI on your browser, which is not supported by Java 6, any version of IE on XP or Android under version 3.0 (and perhaps a few others).
  • greatfire.org doesn't even resolve to that same machine.

It looks like one of your certificates is fine, but clients that don't support SNI won't get to see it. If you want to avoid this problem, get a certificate valid for all 4 names (4 SAN entries), and point greatfire.org to the right IP address too.

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • 1
    Great answer, thanks. I found info specific to our server (NGINX) here: http://nginx.org/en/docs/http/configuring_https_servers.html – GreatFire Mar 31 '12 at 01:51
  • 1
    In essence older clients that don't support SNI will receive the SSL certificate of the default site. I set this to en.greatfire.org for now so those clients can at least view that site. The best solution seems to be to use separate IPs for different hosts. – GreatFire Mar 31 '12 at 01:56