I'm trying to make a HTTPS request from a Java 8 client (using Apache HttpClient 4.3) to a public server (that I don't own). I've never normally had any problems with the requests, but the target server appears to have made some changes and requests started to fail.
Initially, the error was an ValidatorException: PKIX Path Building Failed
but I fixed this by adding the servers certificate to my Java trust store. The error I'm getting now is hostname in certificate didn't match: <target.server.com> != <*.something.else.com> OR <something.else.com>
.
The something.else.com
host is some sort of hosting site etc. anyway I'm satisfied there's nothing suspicious going on. I pulled the certificate for target.server.com
by running the following command:
openssl s_client -connect target.server.com:443 -showcerts
I don't see any reference to target.server.com
in the certificate info, only for something.else.com
. I don't have any problems visiting target.server.com
in a web browser (Chrome) and there are no complaints about the SSL certificate. I added the servers certificate to my trust store using this command:
sudo keytool -import -file /tmp/target.cer -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -alias targetserv
Is there some way I can fix this without a Java code change e.g. adding something to the certificate import command etc. and if not, how else can I get these requests working again.
Here's my HTTP request code (using HttpClient 4.3):
CloseableHttpClient httpClient = HttpClients.custom().setUserAgent(HTTP_USER_AGENT).build();
HttpGet request = new HttpGet(url);
HttpResponse response = httpClient.execute(request);
...throws java.io.IOException: hostname in certificate didn't match
Also, this is the actual target server that I'm trying to reach: https://www.isi.gov.ie
I've tried using HttpClient v4.5 and I still get the same error as with 4.3. I've tried making a request using Java's built HTTP request classes, and the request succeeds (a 302 is returned):
URL obj = new URL("https://www.isi.gov.ie");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
Is there any way I can fix these issues with HttpClient?
It turns out that elsewhere in my application I had been disabling SNI using the Java system property jsse.enableSNIExtension
and I had forgotten about it. The reason I was doing that is because it was the only fix I could find that would prevent ALL HTTP requests using HttpClient from failing with the error:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
How can I re-enable SNI without getting these errors?
I'm using the following version of Java:
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03)
OpenJDK 64-Bit Server VM (build 25.212-b03, mixed mode)