I'm trying to validate X509 certificate chain using sun.security.validator.PKIXValidator according to Oracle official guide. One of the steps in validation is to check CRLs. I'm providing LDAPCertStore to get the CRL from LDAP. But LDAPCertStore cannot handle server closing connection becuase java.security.cert.LDAPCertStoreParameters
lacks settings for LDAPConnection.
Is it possible to amend LDAP connection properties e.g. using LDAP Connection Pooling (system properties doesn't help, bouncy castle has the same implementation regarding connections)? Please see code to reproduce below:
@Test
public void testRevocationListValidation() throws Exception {
String trustStoreFile = "trustStoreFilePath";
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = getClass().getResourceAsStream(trustStoreFile);
if (is == null) {
throw new FileNotFoundException(String.format("KeyStore file '%s' is not found on classpath", trustStoreFile));
}
trustStore.load(is, "password".toCharArray());
Set<TrustAnchor> trustedAnchors = new HashSet<TrustAnchor>();
for (String caCertificateAlias : new String[]{"ca"}) {
X509Certificate certificate = (X509Certificate) trustStore.getCertificate(caCertificateAlias);
trustedAnchors.add(new TrustAnchor(certificate, null));
}
PKIXParameters parameters = new PKIXParameters(trustedAnchors);
CertStore certStore = CertStore.getInstance("LDAP", new LDAPCertStoreParameters("ldapHost", 389));
parameters.setCertStores(Collections.singletonList(certStore));
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(getClass().getResourceAsStream("keystore.jks"), "password".toCharArray());
String keyStoreAlias = "dev-test";
Certificate[] userCertificateChain = keyStore.getCertificateChain(keyStoreAlias);
for (int i = 0; i < 3; i++) {
System.out.println("Starting validation " + i);
CertPath userCertificatePath = CertificateFactory.getInstance("X.509").generateCertPath(Arrays.asList(userCertificateChain));
CertPathValidator.getInstance("PKIX").validate(userCertificatePath, parameters);
System.out.println("Validation " + i + " succeeded");
if (i == 1) {
System.out.println("Sleeping after second validation");
TimeUnit.SECONDS.sleep(90); // Server connection timeout ~ 60 sec
}
}
}
Sample output:
Starting validation 0
Validation 0 succeeded
Starting validation 1
Validation 1 succeeded
Sleeping after second validation
Starting validation 2
java.security.cert.CertPathValidatorException: java.security.cert.CertStoreException: javax.naming.CommunicationException: connection closed [Root exception is java.io.IOException: connection closed]; remaining name
Fixed in Java 9 - LDAP connection would be restored automatically https://bugs.openjdk.java.net/browse/JDK-8059009