You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2019/04/17 07:39:36 UTC
[directory-ldap-api] branch 1.0 updated: o Fix the
LdapNetworConnection so that it works with MINA 2.0.21 (no reason to switch
to 2.1.x) o Added a test for SSL (but it requires a running LDAP server
beside. Use Studio...)
This is an automated email from the ASF dual-hosted git repository.
elecharny pushed a commit to branch 1.0
in repository https://gitbox.apache.org/repos/asf/directory-ldap-api.git
The following commit(s) were added to refs/heads/1.0 by this push:
new 3abbd46 o Fix the LdapNetworConnection so that it works with MINA 2.0.21 (no reason to switch to 2.1.x) o Added a test for SSL (but it requires a running LDAP server beside. Use Studio...)
3abbd46 is described below
commit 3abbd46e7ba821e8c7124426965a8db33d2ca2c1
Author: emmanuel lecharny <el...@apache.org>
AuthorDate: Wed Apr 17 09:39:23 2019 +0200
o Fix the LdapNetworConnection so that it works with MINA 2.0.21 (no
reason to switch to 2.1.x)
o Added a test for SSL (but it requires a running LDAP server beside.
Use Studio...)
---
.../ldap/client/api/LdapNetworkConnection.java | 67 +++----
.../ldap/client/api/LdapSSLConnectionTest.java | 222 +++++++++++++++++++++
2 files changed, 247 insertions(+), 42 deletions(-)
diff --git a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
index 6c2536d..e7a3214 100644
--- a/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
+++ b/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapNetworkConnection.java
@@ -165,10 +165,8 @@ import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.FilterEvent;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolEncoderException;
-import org.apache.mina.filter.ssl.SslEvent;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
@@ -241,9 +239,6 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
/** The exception stored in the session if we've got one */
private static final String EXCEPTION_KEY = "sessionException";
- /** A future used to block any action until the handhake is completed */
- private HandshakeFuture handshakeFuture;
-
// ~~~~~~~~~~~~~~~~~ common error messages ~~~~~~~~~~~~~~~~~~~~~~~~~~
static final String TIME_OUT_ERROR = "TimeOut occurred";
@@ -669,25 +664,6 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
{
connectionFuture = connector.connect( address );
- if ( config.isUseSsl() )
- {
- try
- {
- boolean isSecured = handshakeFuture.get( timeout, TimeUnit.MILLISECONDS );
-
- if ( !isSecured )
- {
- throw new LdapOperationException( ResultCodeEnum.OTHER, I18n.err( I18n.ERR_4100_TLS_HANDSHAKE_ERROR ) );
- }
- }
- catch ( Exception e )
- {
- String msg = "Failed to initialize the SSL context";
- LOG.error( msg, e );
- throw new LdapException( msg, e );
- }
- }
-
boolean result = false;
// Wait until it's established
@@ -2047,6 +2023,27 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
public void messageReceived( IoSession session, Object message ) throws Exception
{
// Feed the response and store it into the session
+ if ( message instanceof SslFilter.SslFilterMessage )
+ {
+ // This is a SSL message telling if the session has been secured or not
+ HandshakeFuture handshakeFuture = ( HandshakeFuture ) session.getAttribute( "HANDSHAKE_FUTURE" );
+
+ if ( message == SslFilter.SESSION_SECURED )
+ {
+ // SECURED
+ handshakeFuture.secured();
+ }
+ else
+ {
+ // UNSECURED
+ handshakeFuture.cancel();
+ }
+
+ session.removeAttribute( "HANDSHAKE_FUTURE" );
+
+ return;
+ }
+
Message response = ( Message ) message;
LOG.debug( "-------> {} Message received <-------", response );
int messageId = response.getMessageId();
@@ -3928,20 +3925,6 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
* {@inheritDoc}
*/
@Override
- public void event( IoSession session, FilterEvent event ) throws Exception
- {
- // Check if it's a SSLevent
- if ( ( event instanceof SslEvent ) && ( ( SslEvent ) event == SslEvent.SECURED ) )
- {
- handshakeFuture.secured();
- }
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
public void sessionClosed( IoSession session ) throws Exception
{
// no need to handle if this session was closed by the user
@@ -4079,9 +4062,6 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
{ "TLSv1", "TLSv1.1", "TLSv1.2" } );
}
- // for LDAPS/startTLS
- handshakeFuture = new HandshakeFuture();
-
if ( ( ldapSession == null ) || !connected.get() )
{
connector.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
@@ -4089,8 +4069,11 @@ public class LdapNetworkConnection extends AbstractLdapConnection implements Lda
else
// for StartTLS
{
- ldapSession.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
+ HandshakeFuture handshakeFuture = new HandshakeFuture();
+ ldapSession.setAttribute( SslFilter.USE_NOTIFICATION, Boolean.TRUE );
+ ldapSession.setAttribute( "HANDSHAKE_FUTURE", handshakeFuture );
+ ldapSession.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
boolean isSecured = handshakeFuture.get( timeout, TimeUnit.MILLISECONDS );
if ( !isSecured )
diff --git a/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapSSLConnectionTest.java b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapSSLConnectionTest.java
new file mode 100644
index 0000000..ecfe50a
--- /dev/null
+++ b/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdapSSLConnectionTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.directory.ldap.client.api;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Network;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ * Test the LdapConnection class by enabling SSL and StartTLS one after the other
+ * (using both in the same test class saves the time required to start/stop another server for StartTLS)
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+
+public class LdapSSLConnectionTest
+{
+ private LdapConnectionConfig sslConfig;
+
+ private LdapConnectionConfig tlsConfig;
+
+
+ @Before
+ public void setup() throws Exception
+ {
+ sslConfig = new LdapConnectionConfig();
+ sslConfig.setLdapHost( Network.LOOPBACK_HOSTNAME );
+ sslConfig.setUseSsl( true );
+ sslConfig.setLdapPort( 10636 );
+ sslConfig.setTrustManagers( new NoVerificationTrustManager() );
+ sslConfig.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+
+ tlsConfig = new LdapConnectionConfig();
+ tlsConfig.setLdapHost( Network.LOOPBACK_HOSTNAME );
+ tlsConfig.setLdapPort( 10389 );
+ tlsConfig.setTrustManagers( new NoVerificationTrustManager() );
+ tlsConfig.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
+ }
+
+
+ /**
+ * Test a successful bind request
+ *
+ * @throws IOException
+ */
+ @Test
+ @Ignore
+ public void testBindRequestSSLConfig() throws Exception
+ {
+ try ( LdapNetworkConnection connection = new LdapNetworkConnection( sslConfig ) )
+ {
+ connection.bind( "uid=admin,ou=system", "secret" );
+
+ assertTrue( connection.getConfig().isUseSsl() );
+ assertTrue( connection.isAuthenticated() );
+ assertTrue( connection.isSecured() );
+ }
+ }
+
+
+ /**
+ * Test a successful bind request
+ *
+ * @throws IOException
+ */
+ @Test
+ @Ignore
+ public void testBindRequestSSLAuto() throws Exception
+ {
+ sslConfig.setTrustManagers( new X509TrustManager[] { new NoVerificationTrustManager() } );
+
+ try ( LdapNetworkConnection connection =
+ new LdapNetworkConnection( sslConfig ) )
+ {
+ connection.bind( "uid=admin,ou=system", "secret" );
+ assertTrue( connection.getConfig().isUseSsl() );
+
+ assertTrue( connection.isAuthenticated() );
+ assertTrue( connection.isSecured() );
+ }
+ }
+
+
+ @Test
+ @Ignore
+ public void testGetSupportedControls() throws Exception
+ {
+ try ( LdapConnection connection = new LdapNetworkConnection( sslConfig ) )
+ {
+ Dn dn = new Dn( "uid=admin,ou=system" );
+ connection.bind( dn.getName(), "secret" );
+
+ List<String> controlList = connection.getSupportedControls();
+ assertNotNull( controlList );
+ assertFalse( controlList.isEmpty() );
+ }
+ }
+
+
+ /**
+ * Test a successful bind request after setting up TLS
+ *
+ * @throws IOException
+ */
+ @Test
+ @Ignore
+ public void testStartTLSBindRequest() throws Exception
+ {
+ try ( LdapNetworkConnection connection = new LdapNetworkConnection( tlsConfig ) )
+ {
+ tlsConfig.setUseTls( true );
+ connection.connect();
+
+ connection.bind( "uid=admin,ou=system", "secret" );
+ assertTrue( connection.isAuthenticated() );
+
+ // try multiple binds with startTLS DIRAPI-173
+ connection.bind( "uid=admin,ou=system", "secret" );
+ assertTrue( connection.isAuthenticated() );
+
+ connection.bind( "uid=admin,ou=system", "secret" );
+ assertTrue( connection.isAuthenticated() );
+ assertTrue( connection.isSecured() );
+
+ connection.unBind();
+ }
+ }
+
+
+ /**
+ * Test a request before setting up TLS
+ *
+ * @throws IOException
+ */
+ @Test
+ @Ignore
+ public void testStartTLSAfterBind() throws Exception
+ {
+ tlsConfig.setTrustManagers( new X509TrustManager[] { new NoVerificationTrustManager() } );
+
+ try ( LdapNetworkConnection connection =
+ new LdapNetworkConnection( tlsConfig ) )
+ {
+ connection.connect();
+
+ connection.bind( "uid=admin,ou=system", "secret" );
+ assertFalse( connection.isSecured() );
+
+ Entry rootDse = connection.getRootDse( "*", "+" );
+
+ assertNotNull( rootDse );
+
+ // startTLS
+ connection.startTls();
+
+ // try multiple binds with startTLS DIRAPI-173
+ assertTrue( connection.isSecured() );
+
+ Entry admin = connection.lookup( "uid=admin,ou=system" );
+
+ assertNotNull( admin );
+ assertEquals( "uid=admin,ou=system", admin.getDn().getName() );
+
+ connection.unBind();
+ }
+ }
+
+
+ @Test
+ @Ignore
+ public void testGetSupportedControlsWithStartTLS() throws Exception
+ {
+ try ( LdapNetworkConnection connection = new LdapNetworkConnection( tlsConfig ) )
+ {
+ tlsConfig.setUseTls( true );
+ connection.connect();
+
+ Dn dn = new Dn( "uid=admin,ou=system" );
+ connection.bind( dn.getName(), "secret" );
+
+ List<String> controlList = connection.getSupportedControls();
+ assertNotNull( controlList );
+ assertFalse( controlList.isEmpty() );
+ }
+ }
+}