I have certificates stored in LDAP server, and we use this certificate to sign the request that will be sent to other system.
and I'm using java.security.cert.CertStore class to retrieve the certificate from LDAP,
however, when my LDAP server is down (for example I have issued a firewall block to ldap server from the server where my application runs) then "CertStore.getInstance("LDAP", ldapCertStoreParams);" doesn't timeout and hangs forever.
I have also used a Future task so that I can timeout the process of connecting in case if it’s taking too long. Even though the Future task times out but still the underlying thread that trying to connect the LDAP is not timing out and hangs indefinitely
After some research I found that there is JNDI property com.sun.jndi.ldap.read.timeout can be used for the LDAP operations, like by setting this in environment variable within JNDI context.
env.put("com.sun.jndi.ldap.read.timeout", "5000");
causes the LDAP service provider to abort the read attempt if the server does not respond with a reply within 5 seconds.
But, since I am using SUN's CertStore provider it doesn't have any facility to set the above property so that thread can timeout if the LDAP server is not responding within a specified time period. I am stuck on how to use this property with CertStore object.
Does anyone have any idea on how to timeout the CertStore.getInstance("LDAP", ldapCertStoreParams) method when the LDAP server is not accessiable?
OR is there any other LDAP provider api where the dead connections are handled properly that can be used to retrieve the certificates from LDAP.
Any help is much appreciated
Below is the code snippet for retrieving the certificates from LDAP.
protected CertStore getLdapCertStore(final CertStoreParameters ldapCertStoreParams) throws InterruptedException, ExecutionException, TimeoutException {
final Callable<CertStore> connectionTask = new Callable<CertStore>() {
public CertStore call() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
return CertStore.getInstance("LDAP", ldapCertStoreParams);
}
};
final Future<CertStore> futureConnection = getCertStoreConnectionExecutor().submit(connectionTask);
return futureConnection.get(connectionTimeoutInSeconds, TimeUnit.SECONDS);
}
private synchronized ExecutorService getCertStoreConnectionExecutor() {
if (certStoreConnectionExecutor == null) {
// We want one thread per connection-setting, as any connection attempt can hang indefinitely if the port is blocked (e.g.: by a firewall)
// NOTE: Cancelling a Future task does NOT guarantee that the associated thread will be freed and returned to the pool, as threads are not forcefully stopped (only *requested* to stop)!
certStoreConnectionExecutor = Executors.newFixedThreadPool(Math.max(1, getLdapHostAndPortList().size()));
}
return certStoreConnectionExecutor;
}