title: jndi LDAPS custom HostnameVerifier and TrustManager
body: <p>We are writing an application that shall connect to different LDAP servers. For each server we may only accept a certain certificate. The hostname in that certificate shall not matter. This is easy, when we use LDAP and STARTTLS, because we can use <code>StartTlsResponse.setHostnameVerifier(..-)</code> and use <code>StartTlsResponse.negotiate(...)</code> with a matching <code>SSLSocketFactory</code>. However we also need to support LDAPS connections. Java supports this natively, but only if the server certificate is trusted by the default java keystore. While we could replace that, we still cannot use different keystores for different servers.</p>
  
  <p>The existing connection code is as follows:</p>
  
  <pre><code>Hashtable&lt;String,String&gt; env = new Hashtable&lt;String,String&gt;();
  env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
  env.put( Context.PROVIDER_URL, ( encryption == SSL ? "ldaps://" : "ldap://" ) + host + ":" + port );
  if ( encryption == SSL ) {
      // env.put( "java.naming.ldap.factory.socket", "CustomSocketFactory" );
  }
  ctx = new InitialLdapContext( env, null );
  if ( encryption != START_TLS )
      tls = null;
  else {
      tls = (StartTlsResponse) ctx.extendedOperation( new StartTlsRequest() );
      tls.setHostnameVerifier( hostnameVerifier );
      tls.negotiate( sslContext.getSocketFactory() );
  }
  </code></pre>
  
  <p>We could add out own <code>CustomSocketFactory</code>, but how to pass information to that?</p>