blob: 324ad185c3a5fb3696d93824d1e35ca7710cc0c1 [file] [log] [blame]
Title: 5.1 - LDAPS
NavPrev: 5-ldap-security.html
NavPrevText: 5 - LDAP Security
NavUp: 5-ldap-security.html
NavUpText: 5 - LDAP Security
NavNext: 5.2-start-tls.html
NavNextText: 5.2 - StartTLS
Notice: Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
# 5.1 - LDAPS
**LDAP** supports **SSL**, it's called **LDAPS**, and it uses a dedicated port. As of today, and since 2000, **LDAPS** is deprecated and **StartTLS** should be used.
That being said, many servers accept **LDAPS**, and the **Apache LDAP API** supports it.
## How does it work ?
The **SSL** protocol ensures that data is transmitted encrypted, and guarantees that the data received is valid. Noone can capture this data and read it, assuming the ciphers used are of sufficient strength.
With **SSL**, a dialog between the client and the server occurs, and when both agree on the particular cipher to use, then all subsequent data is encrypted. This dialog may include a mutual validation of their X.509 certificates.
## Protocols
There are many version that can be used, but the idea is to use the most recent one, if the server supports it. In any case, as we depend on **Java**, we are also limited by the supported version on the client side. Here are all of the existing versions, and their statuses:
| SSLversion | Java 7 Client | Java 7 Server | Java 8 Client | Java 8 Server |
|---|---|---|---|---|
| 2.0 | N/A | N/A | N/A | N/A |
| 3.0 | Disabled | Disabled | N/A | N/A |
| 3.1 (aka TLSv1) | **Enabled** | **Enabled** | **Enabled** | **Enabled** |
| 3.2 (aka TLSv1.1 | Disabled | **Enabled** | **Enabled** | **Enabled** |
| 3.3 (aka TLSv1.2) | Disabled | **Enabled** | **Enabled** | **Enabled** |
(_Disabled_ means it's not active by default, and so must be activated explicitly).
The default is Java will choose the best fit, assuming that it always starts with the newest version (**TLSv1.2**).
Still, you can enforce the version used -- if needed.
## A quick primer
Here is all that is needed to get **LDAPS** connections established with a server :
try ( LdapConnection connection = new LdapNetworkConnection( "server-name", 636, true ) )
{
connection.bind( "uid=admin,ou=system", "secret" );
assertTrue( connection.isAuthenticated() );
}
It's as simple as that! The **636** port is the default **LDAPS** port for standard **LDAP** servers, when running as **root**, and for **ApacheDS** you must pick **10636**. The **true** flag is set to secure the connection. You don't need to close the connection, it will be done automatically upon exiting the try{...} block.
By default, the selected protocol is **TLS**, and the server's certificate is not verified.
## A more sophisticated sample
It's possible to have more control on the **SSL** configuration, and specifically to provide a specific **TrustManager** :
try ( LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPortSSL(),
new NoVerificationTrustManager() ) )
{
connection.bind( "uid=admin,ou=system", "secret" );
assertTrue( ((LdapNetworkConnection)connection).getConfig().isUseSsl() );
assertTrue( connection.isAuthenticated() );
}
Here, we use the _NoVerificationTrustManager_ class, but you may define your own implementation of it. The **Fortress** project uses [this class](https://github.com/apache/directory-fortress-core/blob/master/src/main/java/org/apache/directory/fortress/core/ldap/LdapClientTrustStoreManager.java).
## Using a configuration
One step further : you can define a dedicated configuration that is passed to the constructor. Many parameters can be defined:
* the enabled cipher suites: a list of ciphers that may be used (like "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", etc)
* the enabled protocols: a list of protocals that may be used ( "SSLv3", "TLS", "TLSv1", "TLSv1.1", "TLSv1.2")
* the KeyManager instances
* the SecureRandom instance
* the SSL protocol to use: one of the enabled protocols
* the TrustManager instances
All these parameters are configured using the _LdapConnectionConfig_ class :
LdapConnectionConfig sslConfig = new LdapConnectionConfig();
sslConfig.setLdapHost( Network.LOOPBACK_HOSTNAME );
sslConfig.setUseSsl( true );
sslConfig.setLdapPort( getLdapServer().getPortSSL() );
sslConfig.setTrustManagers( new NoVerificationTrustManager() );
try ( LdapConnection connection = new LdapNetworkConnection( sslConfig ) )
{
connection.bind( "uid=admin,ou=system", "secret" );
assertTrue( ((LdapNetworkConnection)connection).getConfig().isUseSsl() );
assertTrue( connection.isAuthenticated() );
}
## LDAPS or startTLS ?
The important point to understand with **LDAPS** is that every request being exchanged between the client and the server is encrypted, because its underlying transport is encrypted. That means you can't start communicating with the LDAP server before the connection is secured.
It has a few drawbacks:
- first of all, it has an added CPU cost, as everything has to be encrypted and decrypted.
- second, it requires a dedicated port, thus some specific routing rules (firewall, load balancers, etc)
- third, it's a all of nothing choice. If you want to return to a non-encrypted communication, you must use another connection.
This is the why the **startTLS** extended operation should be used instead.