| Title: 5.2 - StartTLS |
| NavPrev: 5.1-ldaps.html |
| NavPrevText: 5.1 - LDAPS |
| NavUp: 5-ldap-security.html |
| NavUpText: 5 - LDAP Security |
| NavNext: 5.3-sasl-bind.html |
| NavNextText: 5.3 - SASL Bind |
| 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.2 - StartTLS |
| |
| As we have seen in the previous chapter, **LDAPS** has some drawbacks. There is a better alternative for securing communications between the client and server -- **startTLS**. |
| |
| The idea is to use an existing connection to send a message to the server and request it to be encrypted. We keep going with the current connection, on the same port, but the exchanged data will continue as encrypted. |
| |
| The **startTLS** extended operation is used for this. It's a pure LDAP request that blocks other requests on the connection until it becomes secured. Of course, if some operations are pending, the operation will not be executed until the pending operations are completed. |
| |
| ## How to use it |
| |
| It's quite simple. You just have to inform an opened connection to send the **startTLS** extended operation. It can be done at any time. Here is a quick example: |
| |
| try ( LdapNetworkConnection connection = |
| new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) ) |
| { |
| connection.connect(); |
| |
| Entry admin = connection.lookup( "uid=admin,ou=system" ); |
| |
| // startTLS |
| connection.startTls(); |
| ... |
| |
| As you can see, we'll used the _startTLS()_ method, and it occurred in the middle of an LDAP session. (There previously was data transmission with the server in clear text). |
| |
| You can also send the _startTLS_ request prior to a bind, protecting the entire session: |
| |
| try ( LdapNetworkConnection connection = |
| new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() ) ) |
| { |
| // startTLS |
| connection.startTls(); |
| |
| Entry admin = connection.lookup( "uid=admin,ou=system" ); |
| ... |
| |
| That's about it... |
| |
| ## Advanced usage |
| |
| We just saw basic usage of the **startTLS** extended operation. Keep in mind that behind the scene, a **TLS** session will be established, which requires some negotiation between the client and the server. It's not different from the establishement of an **LDAPS** connection, except that we're doing it on top of an existing **LDAP** connection. Still, the client and the server must exchange ciphers, certificates, and agree on which protocol version to use. You probably need more control. |
| |
| The **startTLS()** method uses an **LdapConnectionConfig** instance for parameters in order to define things like -- **TrustManagers**, allowed ciphers, enabled protocol versions, **KeyManager** instances, etc. You simply need an **LdapConnectionConfig** instance, and load it with instructions. for example, if you want to use a specific **TrustManager** that doesn't verify the server's certificate: |
| |
| LdapConnectionConfig tlsConfig = new LdapConnectionConfig(); |
| tlsConfig.setLdapHost( Network.LOOPBACK_HOSTNAME ); |
| tlsConfig.setLdapPort( getLdapServer().getPort() ); |
| tlsConfig.setTrustManagers( new NoVerificationTrustManager() ); |
| |
| try ( LdapNetworkConnection connection = |
| new LdapNetworkConnection( tlsConfig ) ) |
| { |
| // Connect |
| connection.connect(); |
| |
| // At this point, we are not oo a secured connection |
| connection.bind( "uid=admin,ou=system", "secret" ); |
| |
| // At this point, we are not oo a secured connection. Let's secure it |
| connection.startTls(); |
| ... |
| |
| In this example, the **startTls** call uses the parameter that was loaded into the _tlsConfig_ instance. |
| |
| ## Here's what isn't supported |
| |
| The [LDAP StartTLS RFC](https://tools.ietf.org/html/rfc2830) requires more than securing connections. Typically, it's possible to stop securing a connection, using a **Graceful Closure** operation. That feature isn't currently supported. |