Previous | Next | Trail Map | Tips for LDAP Users | Security

SSL and Custom Sockets

The simple and CRAM-MD5 authentication mechanisms authenticate the LDAP client to the LDAP server. They do not provide any other security features, such as ensuring that requests sent to the server on that authenticated connection are from the same client, or protecting the privacy of the data exchanged between the client and the server.

To provide higher levels of security for communicating with clients, most LDAP servers allow their services to be accessed through secure sockets, or SSL. Such servers support SSL ports in addition to normal (unprotected) ports. To use this service, the client needs to specify the port number of the SSL port in the Context.PROVIDER_URL(in the API reference documentation)("java.naming.provider.url") property, and to use SSL sockets when communicating with the server.

By default, Sun's LDAP service provider uses plain sockets when communicating with the LDAP server. To request that SSL sockets, you set the Context.SECURITY_PROTOCOL(in the API reference documentation)("java.naming.security.protocol") property to "ssl".

In the following example, the LDAP server is offering SSL at port 636. To run this program, you must enable SSL on port 636 on your LDAP server. This procedure is typically carried out by the directory's administrator.

// Set up environment for creating initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:636/o=JNDITutorial");

// Specify SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");

// Authenticate as S. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

To run this program, you need to have an SSL package that implements the javax.net.SocketFactory interface (see http://java.sun.com/security/ssl/API_users_guide.html for details). The SSL package must be available in your execution environment (such as the HotJavaTM Browser or the JavaTM Web Server) or be added to your classpath. Currently, Sun also provides a standalone SSL implementation, Java Secure Socket Extension. See the bottom of this page for additional information about Java SSL packages.


Note: If you use SSL to connect to a server on a port that is not using SSL, then your program will hang. Similarly, if you use a plain socket to connect to a server's SSL socket, then your application will hang. This is a characteristic of the SSL protocol.

Using SSL with the External SASL Mechanism

SSL provides authentication and other security services at a lower layer than the LDAP. Since authentication has already been done, the LDAP layer can use that authentication information from SSL by using the External SASL mechanism.

The following example is like the SSL example above except instead of using simple authentication, it uses the External SASL authentication. By using External, you do not need to supply any principal or password information because they get picked up from the SSL layer.

// Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Principal & credentials will be obtained from the connection
env.put(Context.SECURITY_AUTHENTICATION, "EXTERNAL");

// Specify SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");

// Create initial context
DirContext ctx = new InitialDirContext(env);

...

Using Custom Sockets

When you set the Context.SECURITY_PROTOCOL property to "ssl", the LDAP provider will attempt to create an SSL socket to communicate with the server using the socket factory javax.net.ssl.SSLSocketFactory. If you want to use a different SSL package, then you need to set the "java.naming.ldap.factory.socket" property to the class name of the socket factory that will produce SSL sockets. This class must implement the javax.net.SocketFactory interface (see http://java.sun.com/security/ssl/API_users_guide.html for details).

SSL sockets are but one type of socket. You can think of other types of sockets that might be useful, such as those for bypassing firewalls. You can use the "java.naming.ldap.factory.socket" property to specify other types of sockets to use. This is useful for setting the socket factory on a per connection basis. If you want to set the socket factory for all sockets used in a program, you should use java.net.Socket.setSocketFactory(). Note that if Context.SECURITY_PROTOCOL is set to "ssl", then the "java.naming.ldap.factory.socket" property should specify a socket factory that produces SSL sockets.

Here is an example that creates an initial context using a custom socket factory:

// Set up environment for creating initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:555/o=JNDITutorial");

// Specify socket factory
env.put("java.naming.ldap.factory.socket", "com.widget.socket.MySocketFactory");

// Create initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

Java SSL Packages

There are other Java APIs, such as Remote Method Invocation (RMI), that use SSL. The RMI documentation includes a list of RMI-SSL related issues, including the Java SSL packages available within and outside of the US. See http://java.sun.com/products/jdk/1.2/docs/guide/rmi/SSLInfo.html for details.

Security: End of Lesson

What's next? Now you can:


Previous | Next | Trail Map | Tips for LDAP Users | Security