->Generating LDAP Certificate to Trusted Java Keys tore for java client:

LDAP Connection Process: You can download this document check here

This document is the purpose of how to generate a keystore file by grabbing the certificate from LDAP server and placing that file in java keystore for java clients, and the information how to Authenticate LDAP server successfully using java client.

First we need to verify if the LDAP server has any certificates in order to connect.

Generating LDAP Certificate to Trusted Java Keys tore for java client:

When working on a client that works with an SSL enabled server running in https/ldaps protocol, you could get error unable to find valid certification path to requested target if the server certificate is not issued by certification authority, but a self signed or issued by a private CMS.

Here is the process how to get the certificate and string into keystore file.

  1. All you need to do is to add the server certificate to your trusted Java key store if your client is written in Java. You might be wondering how as if you cannot access the machine where the server is installed. There is a simple program (InstallCert.java) can help you.

import java.io.*;

import java.net.URL;

import java.security.*;

import java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

public static void main(String[] args) throws Exception {

String host;

int port;

char[] passphrase;

host = “domain”;  //where you LDAP server is runngin

port = 636;

String p = “changeit”;

passphrase = p.toCharArray();

File file = new File(“jssecacerts”);

System.out.println(file.getAbsolutePath());

if (file.isFile() == false) {

char SEP = File.separatorChar;

File dir = new File(System.getProperty(“java.home”) + SEP

+ “lib” + SEP + “security”);

file = new File(dir, “jssecacerts”);

if (file.isFile() == false) {

file = new File(dir, “cacerts”);

}

}

System.out.println(“Loading KeyStore ” + file + “…”);

InputStream in = new FileInputStream(file);

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

ks.load(in, passphrase);

in.close();

SSLContext context = SSLContext.getInstance(“TLS”);

TrustManagerFactory tmf =

TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(ks);

X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];

SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

context.init(null, new TrustManager[] {tm}, null);

SSLSocketFactory factory = context.getSocketFactory();

System.out.println(“Opening connection to ” + host + “:” + port + “…”);

SSLSocket socket = (SSLSocket)factory.createSocket(host, port);

socket.setSoTimeout(10000);

try {

System.out.println(“Starting SSL handshake…”);

socket.startHandshake();

socket.close();

System.out.println ();

System.out.println (“No errors, certificate is already trusted”);

} catch (SSLException e) {

System.out.println ();

e.printStackTrace(System.out);

}

X509Certificate[] chain = tm.chain;

if (chain == null) {

System.out.println (“Could not obtain server certificate chain”);

return;

}

BufferedReader reader =

new BufferedReader(new InputStreamReader(System.in));

System.out.println ();

System.out.println (“Server sent ” + chain.length + ” certificate(s):”);

System.out.println();

MessageDigest sha1 = MessageDigest.getInstance(“SHA1”);

MessageDigest md5 = MessageDigest.getInstance(“MD5″);

for (int i = 0; i < chain.length; i++) {

X509Certificate cert = chain[i];

System.out.println

(” ” + (i + 1) + ” Subject ” + cert.getSubjectDN());

System.out.println(”   Issuer  ” + cert.getIssuerDN());

sha1.update(cert.getEncoded());

System.out.println(”   sha1    ” + toHexString(sha1.digest()));

md5.update(cert.getEncoded());

System.out.println(”   md5     ” + toHexString(md5.digest()));

System.out.println();

}

System.out.println(“Enter certificate to add to trusted keystore or ‘q’ to quit: [1]”);

String line = reader.readLine().trim();

int k;

try {

k = (line.length() == 0) ? 0 : Integer.parseInt(line) – 1;

} catch (NumberFormatException e) {

System.out.println(“KeyStore not changed”);

return;

}

X509Certificate cert = chain[k];

String alias = host + “-” + (k + 1);

ks.setCertificateEntry(alias, cert);

OutputStream out = new FileOutputStream(“jssecacerts”);

ks.store(out, passphrase);

out.close();

System.out.println();

System.out.println(cert);

System.out.println();

System.out.println

(“Added certificate to keystore ‘jssecacerts’ using alias ‘”

+ alias + “‘”);

}

private static final char[] HEXDIGITS = “0123456789abcdef”.toCharArray();

private static String toHexString(byte[] bytes) {

StringBuilder sb = new StringBuilder(bytes.length * 3);

for (int b : bytes) {

b &= 0xff;

sb.append(HEXDIGITS[b >> 4]);

sb.append(HEXDIGITS[b & 15]);

sb.append(‘ ‘);

}

return sb.toString();

}

private static class SavingTrustManager implements X509TrustManager {

private final X509TrustManager tm;

private X509Certificate[] chain;

SavingTrustManager(X509TrustManager tm) {

this.tm = tm;

}

public X509Certificate[] getAcceptedIssuers() {

throw new UnsupportedOperationException();

}

public void checkClientTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

throw new UnsupportedOperationException();

}

public void checkServerTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

this.chain = chain;

tm.checkServerTrusted(chain, authType);

}

}

}

Update that program with the appropriate Input variables like host name, port, and password. Host Name : yahoo.com

This is the host address where LDAP server directory is located.

Port: 636

Mentioned for this LDAP server directory.

Password:  changeit

A password designed to protect the keystore file from tampering. Java level keystores (cacerts and jssecacerts) usually require the password changeit; which is default for SUN LDAP server.

  1. Then execute this program as standalone application directly. This program opened a connection to the specified host and started an SSL handshake. It printed the exception stack trace of the error that occurred and shows you the certificates used by the server. Now it prompts you add the certificate to your trusted KeyStore.
  1. If you want to continue with creating the file add the certificate, then ‘1’, if you want to quit, then ‘q’, or  other numbers to add other certificates, even a CA certificate, but you usually don’t want to do that. Once you have made your choice, the program will display the complete certificate and then added it to a Java KeyStore named ‘jssecacerts’ in the current directory.

Enter 1 and press Enter key, then added certificate to keystore ‘jssecacerts’ using alias ‘domainname-1’ (A mandatory, unique alias for the certificate in the trust store)

  1. To use it in your program, either configure JSSE to use it as its trust store or copy it into your $JAVA_HOME/jre/lib/security directory. If you want all Java applications to recognize the certificate as trusted and not just JSSE, you could also overwrite the cacerts file(This is bad approach) in that directory.

After all that, JSSE will be able to complete a handshake with the host, which you can verify by running the program again.

Authenticating LDAP server with Java Client:

Here is the Test program which helps to authenticate to LDAP successfully.

import javax.naming.*;

import javax.naming.directory.*;

import java.util.Hashtable;

/**

* Demonstrates how to create an initial context to an LDAP server

* using simple authentication.

*/

class SimpleAuthenticate {

public static void main(String[] args) {

Hashtable authEnv = new Hashtable(11);

String passWord = “pass_1234”;

String dn = “uid=skk27,ou=People,dc=domain,dc=edu”;

String ldapURL = ” ldaps://host:636″;

authEnv.put(Context.INITIAL_CONTEXT_FACTORY,”com.sun.jndi.ldap.LdapCtxFactory”);

authEnv.put(Context.PROVIDER_URL, ldapURL);

authEnv.put(Context.SECURITY_AUTHENTICATION, “simple”);

authEnv.put(Context.SECURITY_PRINCIPAL, dn);

authEnv.put(Context.SECURITY_CREDENTIALS, passWord);

try {

DirContext authContext = new InitialDirContext(authEnv);

System.out.println(“Authentication Success!”);

} catch (AuthenticationException authEx) {

System.out.println(“Authentication failed!”);

} catch (NamingException namEx) {

System.out.println(“Something went wrong!”);

namEx.printStackTrace();

}

}

}

Explanation:

1)      authEnv.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);

Constant that holds the name of the environment property for specifying the initial context factory to use. We need to use fully qualified Ldap context object.

Here we are using “com.sun.jndi.ldap.LdapCtxFactory”, The Naming context factory that wraps the SUN LDAP factory.

2)  authEnv.put(Context.PROVIDER_URL, ldapURL);

Constant that holds the URL where the LDAP server is running with port number

3)   authEnv.put(Context.SECURITY_AUTHENTICATION, “simple”);

Specifies the authentication mechanism to use. For the Sun LDAP service provider, this can be one of the following strings: "none", "simple", “SASL”. In our case we used “simple” which is already set for this LDAP server.

4)      authEnv.put(Context.SECURITY_PRINCIPAL, dn);

Constant that holds the name of the environment property for specifying the identity of the principal for authenticating the caller to the service. The format of the principal depends on the authentication scheme. If this property is unspecified, the behavior is determined by the service provider.

In order to authenticate on LDAP, we need to build the DN like in the following.

Ex: dn = “uid=skk27,ou=People,dc=domain,dc=edu”;

As per LDAP authentication we need create the DN like the above, here

uid = User ID, in the LDAP server

ou = Organizational Unit, which is assigned during the creation of account for uid in the LDAP directory.

dc = Domain Component, here domain.edu (like yahoo.com) is the domain component.

5) authEnv.put(Context.SECURITY_CREDENTIALS, passWord);

Constant that holds the name of the environment property for specifying the credentials of the principal for authenticating the caller to the service.

Password on uid’s account.

>Javac SimpleAuthenticate.java

>Java SimpleAuthenticate

If you get the Message “Authentication Success!”, then you got to Authenticate Successfully.

Advertisements