LDAP over SSL/TLS and StartTLS

There are two approaches to make secure connections to LDAP servers. One is LDAP over SSL/TLS (LDAPS) and the other is StartTLS. I have quickly tried them by using Apache Directory LDAP API (version 1.0.0-M20) and UnboundID LDAP SDK for Java (version 2.3.5). The LDAP server in my environment is OpenLDAP (version 2.4.38) with SSL/TLS enabled by OpenSSL (version 1.0.1e).

LDAP over SSL/TLS

In case of Apache’s API, one of the constructors of LdapNetworkConnection class accepts an instance of LdapConnectionConfig class which contains the configuration required for SSL/TLS. Supposing that the provided trust managers are already configured to trust my self-signed certificate of the LDAP server, the following code will connect to the server over SSL/TLS.

        TrustManager[] trustManagers = ...
        
        LdapConnectionConfig config = new LdapConnectionConfig();
        config.setLdapHost("192.168.1.1");
        config.setLdapPort(636);
        config.setTrustManagers(trustManagers);
        config.setUseSsl(true);
        LdapConnection conn = new LdapNetworkConnection(config);
        
        try {
            conn.connect();
            conn.bind("cn=Manager,dc=localdomain", "secret");
            
            // ... Do something
            
        } catch (LdapException e) {
            // ...
        } finally {
            // ...
        }

In case of UnboundID’s SDK, LDAPConnection class has several contructors, some of which accept a SocketFactory instance. UnboundID also provides a utility class that helps you create a SocketFactory instance. That is SSLUtil class. Below is a sample code.

        TrustManager[] trustManagers = ...
        
        LDAPConnection conn = null;
        
        try {
            SSLUtil sslUtil = new SSLUtil(trustManagers);
            SocketFactory factory
                = sslUtil.createSSLSocketFactory();
            
            conn = new LDAPConnection(factory, "192.168.1.1", 636);
            conn.bind("cn=Manager,dc=localdomain", "secret");
            
            // ... Do something
            
        } catch (GeneralSecurityException | LDAPException e) {
            // ...
        } finally {
            // ...
        }

The code can be a little more compact by using UnboundID’s SDK than by Apache’s API.

StartTLS

It seems that OpenLDAP Faq-O-Matic: Start TLS v. ldaps:// prefers StartTLS to LDAP over SSL/TLS as quoted below, though I am not sure whether it is the majority view or not.

The StartTLS extended operation [RFC 2830] is LDAPv3’s standard mechanism for enabling TLS (SSL) data confidentiality protection. The mechanism uses an LDAPv3 extended operation to establish an encrypted SSL/TLS connection within an already established LDAP connection. While the mechanism is designed for use with TLSv1, most implementations will fallback to SSLv3 (and SSLv2) if necessary.

ldaps:// is a mechanism for establishing an encrypted SSL/TLS connection for LDAP. It requires use of separate port, commonly 636. Though originally designed for use with LDAPv2 and SSLv2, many implementations support its use with LDAPv3 and TLSv1. Although there is no technical specification for ldaps:// it is widely used.

ldaps:// is deprecated in favor of Start TLS [RFC2830]. OpenLDAP 2.0 supports both.

For security reasons the server should be configured not to accept SSLv2.

I had a little trouble in knowing how to do StartTLS as an extended operation by using Apache’s API, because I could not find a straightforward class that implements ExtendedRequest interface and represents a StartTLS request. Finally I found a way out.

        TrustManager[] trustManagers = ...
        
        LdapConnectionConfig config = new LdapConnectionConfig();
        config.setLdapHost("192.168.1.1");
        config.setLdapPort(389);
        config.setTrustManagers(trustManagers);
        config.setUseTls(true);
        LdapConnection conn = new LdapNetworkConnection(config);
        
        try {
            
            conn.connect();
            conn.bind("cn=Manager,dc=localdomain", "secret");
            
            // ... Do something
            
        } catch (LdapException e) {
            // ...
        } finally {
            // ...
        }

The above is almost similar to the code for LDAP over SSL/TLS, except that the configuration is a little modified. setUseSsl method is replaced with setUseTls method. But I am not sure whether I am on the right track or not. Neither the relevant pages of the official documents, e.g. 5 – LDAP Security — Apache Directory, nor the Javadoc describes the detail yet.

In case of UnboundID’s SDK, it can be done by creating a StartTLSExtendedRequest instance. SSLUtil class helps again to create a SSLContext instance at this time.

        TrustManager[] trustManagers = ...
        
        LDAPConnection conn = null;
        
        try {
            
            SSLUtil sslUtil = new SSLUtil(trustManagers);
            SSLContext context = sslUtil.createSSLContext();
            ExtendedRequest extRequest
                = new StartTLSExtendedRequest(context);
            
            conn = new LDAPConnection("192.168.1.1", 389);
            conn.processExtendedOperation(extRequest);
            conn.bind("cn=Manager,dc=localdomain", "secret");
            
            // ... Do something
            
        } catch (GeneralSecurityException | LDAPException e) {
            // ...
        } finally {
            // ...
        }

It is more intuitive and straightforward for me to treat StartTLS as an extended operation than to treat it as an element of the configuration of the connection. UnboundID’s approach gives you a free hand to shift from nonsecure data transfer to secure one anytime you like, while Apache’s approach forces you to determine whether to use it or not in the very beginning. I think UnboundID’s approach is more compliant to the intent and specification of StartTLS.

Advertisements

About tt4cs

I am a post-sale service engineer working in Tokyo for a Singapore-based software development company, which provides authentication and access management solutions for global and regional financial institutions in Asia-Pacific region.
This entry was posted in Java, LDAP and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s