Unable to connect to AD via SSL Connection
Hello,
I am trying to connect to AD via SSL, but get the exception below. Any ideas on what the probem maybe? I am using temp certs from Verisign that imported into keystore that I called jboss.jks.
String urlAD = "ldaps://win2003srv.diamelle.local:636";
envDC.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
envDC.put(Context.SECURITY_AUTHENTICATION,"simple");
envDC.put(Context.SECURITY_PRINCIPAL,"administrator@diamelle.local");
envDC.put(Context.SECURITY_CREDENTIALS,"sasNY257");
envDC.put(Context.PROVIDER_URL,urlAD);
envDC.put(Context.REFERRAL,"follow");
envDC.put(Context.SECURITY_PROTOCOL,"ssl");
System.setProperty("javax.net.ssl.trustStore", "E:\\devtool\\j2sdk1.4.2_11\\bin\\jboss.jks");
LdapContext ctxDC = new InitialLdapContext(envDC,null);
- Exception
javax.naming.CommunicationException: simple bind failed: win2003srv.diamelle.local:636 [Root exception is javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]
at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.ldap.InitialLdapContext.<init>(Unknown Source)
at com.diamelle.connector.ad.TestClient.main(TestClient.java:96)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
at java.io.BufferedOutputStream.flush(Unknown Source)
at com.sun.jndi.ldap.Connection.writeRequest(Unknown Source)
at com.sun.jndi.ldap.LdapClient.ldapBind(Unknown Source)
... 12 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
... 20 more
[2722 byte] By [
shah70a] at [2007-10-3 5:05:08]

if you use windows 2003, these are the steps to enable ssl for AD:
1) Install certificate component. open control panel on the domain controller machine -> add or remove programs -> click add/remove windows components -> check certificate services to install this component (you may select default setting if you are unsure, also it may ask you install IIS).
2)set policy. open Domain Controller Security Policy from Administrative tools ->look at "Public Key Policies" -> right click on "Automatic Certificate Request Settings" and select "New Automatic Certicate Request" -> under certificate templates click on "Computer" (also you will see "Domain Controller" ,you will select it for later use)->click next and click finish. And do the same again to choose "Domain Controller". finally you will see two entries in "Automatic certificate request settings": one is "computer", the other is "domain controller".
now you can access windows2003 by SSL connection. similar steps in win2000.
If you don't want create keystone file , you maybe need the follow code:
1) create your trust manager:
public class myTrustManager implements X509TrustManager {
private KeyStore keyStore;
/** Creates a new instance of metapassTrustManager */
public metapassTrustManager(KeyStore keystore) {
keyStore = keystore;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{
//if you want handle ,enable it
// if(!isChainTrusted(chain)) throw new CertificateException("the certificate is not trusted by client");
}
public void checkServerTrusted(X509Certificate[] chain,String authType){
//if you want accept server certificate from connection, enable it.
// isServerTrusted(chain);
}
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] X509Certs = null;
try {
// See how many certificates are in the keystore.
int numberOfEntry = keyStore.size();
// If there are any certificates in the keystore.
if(numberOfEntry > 0) {
// Create an array of X509Certificates
X509Certs = new X509Certificate[numberOfEntry];
// Get all of the certificate alias out of the keystore.
Enumeration aliases = keyStore.aliases();
// Retrieve all of the certificates out of the keystore
// via the alias name.
int i = 0;
while (aliases.hasMoreElements()) {
X509Certs =
(X509Certificate)keyStore.
getCertificate((String)aliases.nextElement());
i++;
}
}
} catch( Exception e ) {
System.out.println( "getAcceptedIssuers Exception: "
+ e.toString() );
X509Certs = null;
}
return X509Certs;
}
private boolean isChainTrusted(X509Certificate[] chain) {
boolean trusted = false;
try {
// Start with the root and see if it is in the Keystore.
// The root is at the end of the chain.
for (int i = chain.length - 1; i >= 0; i-- ) {
if (keyStore.getCertificateAlias(chain) != null) {
trusted = true;
break;
}
}
} catch( Exception e ) {
System.out.println( "isChainTrusted Exception: "
+ e.toString() );
trusted = false;
}
return trusted;
}
public boolean isServerTrusted(X509Certificate[] chain) {
boolean trusted = false;
try {
// See if the chain is in the keyStore object.
trusted = isChainTrusted(chain);
// If certificate is untrusted
if(!trusted) {
for (int i = 0; i < chain.length; i++) {
keyStore.setCertificateEntry
(chain.getIssuerDN().toString(), chain);
}
trusted = true;
}
} catch( Exception e ) {
System.out.println( "isServerTrusted Error: " + e.toString() );
trusted = false;
}
return trusted;
}
}
2):create a SSLSocketFactory class and in initSSL function , it use the myTrustManager class.
public class LDAPSSLSocketFactory extends SocketFactory {
private static SocketFactory factory;
/** Creates a new instance of LDAPSSLSocketFactory */
public LDAPSSLSocketFactory() {
}
private boolean initSSL(){
boolean isDone = false;
try {
KeyStore keyStore = null;
SSLContext context = null;
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
TrustManager[] tms = {new myTrustManager(keyStore)};
context = SSLContext.getInstance("TLS", "SunJSSE");
context.init(null, tms, null);
factory = context.getSocketFactory();
isDone = true;
} catch (KeyManagementException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (NoSuchProviderException ex) {
ex.printStackTrace();
} catch (KeyStoreException ex) {
ex.printStackTrace();
} catch (CertificateException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return isDone;
}
public static SocketFactory getDefault() {
return new LDAPSSLSocketFactory();
}
public Socket createSocket(String host, int port)
throws IOException, UnknownHostException {
if(initSSL())
return factory.createSocket(host, port);
else throw new IOException("SSL ERROR");
}
public Socket createSocket(String host, int port, InetAddress localHost,
int localPort) throws IOException, UnknownHostException {
if(initSSL())
return factory.createSocket(host, port, localHost, localPort);
else throw new IOException("SSL ERROR");
}
public Socket createSocket(InetAddress host, int port) throws IOException {
if(initSSL())
return factory.createSocket(host, port);
else throw new IOException("SSL ERROR");
}
public Socket createSocket(InetAddress address, int port,
InetAddress localAddress, int localPort) throws IOException {
if(initSSL())
return factory.createSocket(address, port, localAddress, localPort);
else throw new IOException("SSL ERROR");
}
}
3) Finally, in you ldap function , add the factory class into your enviroment like this:
env.put("java.naming.ldap.factory.socket", "LDAPSSLSocketFactory");// if the LDAPSSLSocketFactory belong to a package, you should include the package name like com.company.LDAPSSLSocketFactory
envDC.put(Context.SECURITY_AUTHENTICATION,"simple");
...
//envDC.put(Context.SECURITY_PROTOCOL,"ssl"); //no need it.
......