As far as I know, all you can do is pass a class name (see icrovett's answer) and JNDI will call the getDefault() method via reflection. So you can't really pass any arguments there. So I think there is no nice and clean solution.
For my needs, I've built a SelectiveLdapSslSocketFactory
, which contains a static Map mapping hosts to different SSLSocketFactories. First, you can register your custom SSLSocketFactories
for different hosts. Then, when any of the createSocket(...)
methods is called, it knows the host the socket is created for so the call can be delegated to the corresponding SSLSocketFactory
. It also contains a defaultSslSocketFactory
used for hosts without any mapping and also in the getDefaultCipherSuites()
and getSupportedCipherSuites()
methods. I'm not sure, if it's completely correct but it works fine for me so test it if you like:
public class SelectiveLdapSslSocketFactory extends SSLSocketFactory {
private static SSLSocketFactory defaultSslSocketFactory;
private static final Map<String, SSLSocketFactory> hostToSslSocketFactoryMap = new HashMap<>();
{
try {
defaultSslSocketFactory = <yourOwnDefaultSslSocketFactory>;
} catch (Exception ex) {
Logger.warn(ex, "Couldn't initialize a defaultSslSocketFactory for LDAP connections!");
}
}
public static SSLSocketFactory getRegisteredSslSocketFactory(String host) {
return hostToSslSocketFactoryMap.get(host);
}
public static void registerSslSocketFactory(String host, SSLSocketFactory sslSocketFactory) {
hostToSslSocketFactoryMap.put(host, sslSocketFactory);
}
public static void deregisterSslSocketFactory(String host) {
hostToSslSocketFactoryMap.remove(host);
}
public SelectiveLdapSslSocketFactory() {
}
public static SocketFactory getDefault() {
return new SelectiveLdapSslSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return defaultSslSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return defaultSslSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
SSLSocketFactory sslSocketFactory = Objects.requireNonNullElse(hostToSslSocketFactoryMap.get(host), defaultSslSocketFactory);
return sslSocketFactory.createSocket(s, host, port, autoClose);
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
SSLSocketFactory sslSocketFactory = Objects.requireNonNullElse(hostToSslSocketFactoryMap.get(host), defaultSslSocketFactory);
return sslSocketFactory.createSocket(host, port);
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
SSLSocketFactory sslSocketFactory = Objects.requireNonNullElse(hostToSslSocketFactoryMap.get(host), defaultSslSocketFactory);
return sslSocketFactory.createSocket(host, port, localHost, localPort);
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocketFactory sslSocketFactory = getSslSocketFactory(host);
return sslSocketFactory.createSocket(host, port);
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
SSLSocketFactory sslSocketFactory = getSslSocketFactory(address);
return sslSocketFactory.createSocket(address, port, localAddress, localPort);
}
private SSLSocketFactory getSslSocketFactory(InetAddress inetAddress) {
SSLSocketFactory sslSocketFactory = hostToSslSocketFactoryMap.get(Objects.requireNonNullElse(inetAddress.getCanonicalHostName(), ""));
if (sslSocketFactory == null) {
sslSocketFactory = hostToSslSocketFactoryMap.get(Objects.requireNonNullElse(inetAddress.getHostName(), ""));
if (sslSocketFactory == null) {
sslSocketFactory = hostToSslSocketFactoryMap.get(Objects.requireNonNullElse(inetAddress.getHostAddress(), ""));
if (sslSocketFactory == null) {
sslSocketFactory = defaultSslSocketFactory;
}
}
}
return sslSocketFactory;
}
}
You can then use it like:
...
SelectiveLdapSslSocketFactory.registerSslSocketFactory(host01, sslSocketFactory01);
SelectiveLdapSslSocketFactory.registerSslSocketFactory(host02, sslSocketFactory02);
SelectiveLdapSslSocketFactory.registerSslSocketFactory(host03, sslSocketFactory03);
props.put("java.naming.ldap.factory.socket", SelectiveLdapSslSocketFactory.class.getName());