SSLSocket ignores domain mismatch

The SSL/TLS protocol specification is modular and detached from the specifications used to authenticate the remote host. These other specifications are split into two categories: verifying that the certificate itself can be trusted (RFC 3280/5280) and verifying the identity in the certificate (RFC 6125, or RFC 2818 for HTTPS).

The JSSE integrates the SSL protocol and the verification of the certificate in the SSLSocket (or SSLEngine) API, but doesn’t handle the verification of the identifier (whch is equally important).

This is mainly due to the fact that the SSLSocket/SSLEngine can apply to any application protocol (e.g. HTTP, IMAP, SMTP, LDAP, …), but the rules for verifying the identifier were in different specifications (with small variations), until RFC 6125 (which is still quite recent).

HttpsURLConnection handles both, because it also uses a HostnameVerifier, which follows the HTTPS specification (RFC 2818, Section 3.1). This is done separately from the SSLSocket/SSLEngine API.
For other protocols, you may need to implement what the protocol specification says.

This being said, since Java 7, there is a mechanism to verify the identity of the certificate directly as part of the SSLSocket/SSLEngine API.

SSLParameters sslParams = new SSLParameters();
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
sslSocket.setSSLParameters(sslParams);

Using this should make it throw an exception if the host name doesn’t match.

There aren’t major differences between HTTPS and the more uniform specifications in RFC 6125 (besides the fact that the latter considers IP addresses out of scope). Even if you’re not using HTTPS, it would still generally make sense to use its identification specifications for other protocols. (Perhaps an “RFC 6125” endpoint identification algorithm might come in later versions of Java.)

Leave a Comment