directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From seelm...@apache.org
Subject [directory-studio] branch master updated: DIRSTUDIO-1219: Ensure StartTLS on connect
Date Fri, 04 Jun 2021 17:52:59 GMT
This is an automated email from the ASF dual-hosted git repository.

seelmann pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-studio.git


The following commit(s) were added to refs/heads/master by this push:
     new b53667a  DIRSTUDIO-1219: Ensure StartTLS on connect
b53667a is described below

commit b53667ab3b87afcfcd6f1b1df90d733636cfc888
Author: Stefan Seelmann <mail@stefan-seelmann.de>
AuthorDate: Fri Jun 4 19:49:56 2021 +0200

    DIRSTUDIO-1219: Ensure StartTLS on connect
    
    * Call startTls() right after connect()
    * Change icon and label to indicate that connection is secured
    * Remove unused SASL Plain mechanism and cleanup related code
    * Add several test scenarios
---
 .../connection/core/ConnectionParameter.java       |  25 +-
 .../directory/studio/connection/core/Messages.java |   1 +
 .../connection/core/io/ConnectionWrapper.java      |  10 +-
 .../core/io/api/DirectoryApiConnectionWrapper.java |  98 ++--
 .../studio/connection/core/messages.properties     |   1 +
 .../studio/connection/core/messages_de.properties  |   1 +
 .../studio/connection/core/messages_fr.properties  |   1 +
 .../ui/widgets/AuthenticationParameterPage.java    |  27 -
 .../ui/widgets/ConnectionLabelProvider.java        |  23 +-
 .../core/DirectoryApiConnectionWrapperTest.java    | 370 ++++++++++---
 .../integration/junit5/ApacheDirectoryServer.java  |  10 +-
 .../integration/junit5/Fedora389dsLdapServer.java  |  15 +
 .../test/integration/junit5/OpenLdapServer.java    |  28 +-
 .../test/integration/junit5/TestLdapServer.java    |  22 +-
 .../test/integration/junit5/OpenLdapConfig.ldif    |   3 +-
 .../test/integration/ui/AbstractTestBase.java      |  16 +
 .../integration/ui/CertificateValidationTest.java  |  14 -
 .../integration/ui/NewConnectionWizardTest.java    | 607 +++++++++++++++------
 .../studio/test/integration/ui/bots/WizardBot.java |   7 +
 19 files changed, 904 insertions(+), 375 deletions(-)

diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
index caa01df..6ef9acf 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
@@ -55,6 +55,13 @@ public class ConnectionParameter
 
         /** Encryption using Start TLS extension. */
         START_TLS
+
+        ;
+
+        public boolean isEncrytped()
+        {
+            return this != NONE;
+        }
     }
 
     /**
@@ -77,19 +84,16 @@ public class ConnectionParameter
         SASL_CRAM_MD5(3),
 
         /** SASL authentication using GSSAPI. */
-        SASL_GSSAPI(4),
-        
-        /** SASL PLAIN authentication */
-        SASL_PLAIN(5);
-        
-        
+        SASL_GSSAPI(4);
+
         private int value;
-        
+
         private AuthenticationMethod( int value )
         {
             this.value = value;
         }
 
+
         public int getValue()
         {
             return value;
@@ -165,11 +169,10 @@ public class ConnectionParameter
 
     /** The extended properties. */
     private Map<String, String> extendedProperties;
-    
+
     /** The connection timeout. Default to 30 seconds */
     private long timeoutMillis = 30000L;
 
-
     /**
      * Creates a new instance of ConnectionParameter.
      */
@@ -756,7 +759,7 @@ public class ConnectionParameter
     public int getExtendedIntProperty( String key )
     {
         String s = extendedProperties.get( key );
-        
+
         if ( s != null )
         {
             return Integer.parseInt( s );
@@ -790,7 +793,7 @@ public class ConnectionParameter
     public boolean getExtendedBoolProperty( String key )
     {
         String s = extendedProperties.get( key );
-        
+
         if ( s != null )
         {
             return Boolean.parseBoolean( s );
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
index 865636c..9f6bd9c 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
@@ -89,5 +89,6 @@ public class Messages extends NLS
 
     public static String DirectoryApiConnectionWrapper_NoConnection;
     public static String DirectoryApiConnectionWrapper_UnableToConnect;
+    public static String DirectoryApiConnectionWrapper_UnsecuredConnection;
 
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
index b92b122..7c7d1ff 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
@@ -32,9 +32,9 @@ import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
-import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
+import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 
 
@@ -82,6 +82,14 @@ public interface ConnectionWrapper
 
 
     /**
+     * Checks if the connection is secured.
+     * 
+     * @return true, if is secured
+     */
+    boolean isSecured();
+
+
+    /**
      * Sets the binary attributes.
      * 
      * @param binaryAttributes the binary attributes
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
index 949fe30..8c7c694 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
@@ -76,7 +76,6 @@ import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.ldap.client.api.SaslCramMd5Request;
 import org.apache.directory.ldap.client.api.SaslDigestMd5Request;
 import org.apache.directory.ldap.client.api.SaslGssApiRequest;
-import org.apache.directory.ldap.client.api.SaslPlainRequest;
 import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
@@ -109,33 +108,21 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
     /** The search request number */
     private static int searchRequestNum = 0;
 
-    /** The connection*/
+    /** The Studio connection  */
     private Connection connection;
 
-    /** The LDAP Connection Configuration */
+    /** The LDAP connection configuration */
     private LdapConnectionConfig ldapConnectionConfig;
 
-    /** The LDAP Connection */
+    /** The LDAP connection */
     private LdapNetworkConnection ldapConnection;
 
     /** The binary attribute detector */
     private DefaultConfigurableBinaryAttributeDetector binaryAttributeDetector;
 
-    /** Indicates if the wrapper is connected */
-    private boolean isConnected = false;
-
     /** The current job thread */
     private Thread jobThread;
 
-    /** The bind principal */
-    private String bindPrincipal;
-
-    /** The bind password */
-    private String bindPassword;
-
-    /** The SASL PLAIN authzid */
-    private String authzId;
-
     /**
      * Creates a new instance of DirectoryApiConnectionWrapper.
      * 
@@ -153,7 +140,6 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
     public X509Certificate[] connect( StudioProgressMonitor monitor )
     {
         ldapConnection = null;
-        isConnected = false;
         jobThread = null;
 
         try
@@ -172,7 +158,6 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
     private X509Certificate[] doConnect( final StudioProgressMonitor monitor ) throws Exception
     {
         ldapConnection = null;
-        isConnected = true;
 
         ldapConnectionConfig = new LdapConnectionConfig();
         ldapConnectionConfig.setLdapHost( connection.getHost() );
@@ -231,6 +216,12 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
         {
             public void run()
             {
+                /*
+                 * Use local temp variable while the connection is being established and secured.
+                 * This process can take a while and the user might be asked to inspect the server
+                 * certificate. During that process the connection must not be used.
+                 */
+                LdapNetworkConnection ldapConnectionUnderConstruction = null;
                 try
                 {
                     // Set lower timeout for connecting
@@ -238,13 +229,13 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
                     ldapConnectionConfig.setTimeout( Math.min( oldTimeout, 5000L ) );
 
                     // Connecting
-                    ldapConnection = new LdapNetworkConnection( ldapConnectionConfig );
-                    boolean connected = ldapConnection.connect();
+                    ldapConnectionUnderConstruction = new LdapNetworkConnection( ldapConnectionConfig );
+                    ldapConnectionUnderConstruction.connect();
 
-                    // Establish TLS layer if TLS is enabled and SSL is not
+                    // DIRSTUDIO-1219: Establish TLS layer if TLS is enabled and SSL is not
                     if ( ldapConnectionConfig.isUseTls() && !ldapConnectionConfig.isUseSsl() )
                     {
-                        ldapConnection.startTls();
+                        ldapConnectionUnderConstruction.startTls();
                     }
 
                     // Capture the server certificates
@@ -253,11 +244,23 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
                         serverCertificates.set( studioTrustmanager.get().getChain() );
                     }
 
-                    if ( !connected )
+                    // Now set the LDAP connection once the (optional) security layer is in place
+                    ldapConnection = ldapConnectionUnderConstruction;
+
+                    if ( !isConnected() )
                     {
                         throw new Exception( Messages.DirectoryApiConnectionWrapper_UnableToConnect );
                     }
 
+                    // DIRSTUDIO-1219: Verify secure connection if ldaps:// or StartTLS is configured
+                    if ( ldapConnectionConfig.isUseTls() || ldapConnectionConfig.isUseSsl() )
+                    {
+                        if ( !isSecured() || serverCertificates.get() == null )
+                        {
+                            throw new Exception( Messages.DirectoryApiConnectionWrapper_UnsecuredConnection );
+                        }
+                    }
+
                     // Set old timeout again
                     ldapConnectionConfig.setTimeout( oldTimeout );
                 }
@@ -267,9 +270,9 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
 
                     try
                     {
-                        if ( ldapConnection != null )
+                        if ( ldapConnectionUnderConstruction != null )
                         {
-                            ldapConnection.close();
+                            ldapConnectionUnderConstruction.close();
                         }
                     }
                     catch ( Exception exception )
@@ -320,7 +323,6 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
             ldapConnection = null;
             binaryAttributeDetector = null;
         }
-        isConnected = false;
     }
 
 
@@ -351,26 +353,9 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
     }
 
 
-    private BindResponse bindSaslPlain() throws LdapException
-    {
-        SaslPlainRequest saslPlainRequest = new SaslPlainRequest();
-        saslPlainRequest.setUsername( bindPrincipal );
-        saslPlainRequest.setCredentials( bindPassword );
-        saslPlainRequest.setAuthorizationId( authzId );
-        saslPlainRequest
-            .setQualityOfProtection( connection.getConnectionParameter().getSaslQop() );
-        saslPlainRequest.setSecurityStrength( connection.getConnectionParameter()
-            .getSaslSecurityStrength() );
-        saslPlainRequest.setMutualAuthentication( connection.getConnectionParameter()
-            .isSaslMutualAuthentication() );
-
-        return ldapConnection.bindSaslPlain( bindPrincipal, bindPassword, authzId );
-    }
-
-
     private void doBind( final StudioProgressMonitor monitor ) throws Exception
     {
-        if ( ldapConnection != null && isConnected )
+        if ( isConnected() )
         {
             InnerRunnable runnable = new InnerRunnable()
             {
@@ -413,21 +398,14 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
                                 monitor.reportError( Messages.model__no_credentials, exception );
                                 throw exception;
                             }
-                            bindPrincipal = credentials.getBindPrincipal();
-                            bindPassword = credentials.getBindPassword();
+                            String bindPrincipal = credentials.getBindPrincipal();
+                            String bindPassword = credentials.getBindPassword();
 
                             switch ( connection.getConnectionParameter().getAuthMethod() )
                             {
                                 case SIMPLE:
                                     // Simple Authentication
                                     bindResponse = bindSimple( bindPrincipal, bindPassword );
-
-                                    break;
-
-                                case SASL_PLAIN:
-                                    // SASL Plain authentication
-                                    bindResponse = bindSaslPlain();
-
                                     break;
 
                                 case SASL_CRAM_MD5:
@@ -555,6 +533,15 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
     /**
      * {@inheritDoc}
      */
+    public boolean isSecured()
+    {
+        return isConnected() && ldapConnection.isSecured();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public void setBinaryAttributes( Collection<String> binaryAttributes )
     {
         if ( binaryAttributeDetector != null )
@@ -1212,7 +1199,7 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
         throws Exception
     {
         // check connection
-        if ( !isConnected || ldapConnection == null )
+        if ( !isConnected() )
         {
             doConnect( monitor );
             doBind( monitor );
@@ -1266,11 +1253,8 @@ public class DirectoryApiConnectionWrapper implements ConnectionWrapper
                         {
                         }
 
-                        isConnected = false;
                         ldapConnection = null;
                     }
-
-                    isConnected = false;
                 }
             };
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
index 5619285..aafd382 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
@@ -56,3 +56,4 @@ StudioKeyStoreManager_CantRemoveCertificateFromTrustStore=Can't remove certifica
 
 DirectoryApiConnectionWrapper_NoConnection=No Connection
 DirectoryApiConnectionWrapper_UnableToConnect=Unable to connect
+DirectoryApiConnectionWrapper_UnsecuredConnection=Unsecured connection
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
index ad95505..cb40eb0 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
@@ -58,3 +58,4 @@ StudioKeyStoreManager_CantRemoveCertificateFromTrustStore=Fehler beim L\u00FCsch
 
 DirectoryApiConnectionWrapper_NoConnection=Keine Verbindung
 DirectoryApiConnectionWrapper_UnableToConnect=Verbindung nicht m�glich
+DirectoryApiConnectionWrapper_UnsecuredConnection=Unsichere Verbindung
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
index ba7e52b..74cd0fa 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
@@ -58,3 +58,4 @@ StudioKeyStoreManager_CantRemoveCertificateFromTrustStore=Impossible de supprime
 
 DirectoryApiConnectionWrapper_NoConnection=Pas de connexion
 DirectoryApiConnectionWrapper_UnableToConnect=Impossible de se connecter
+DirectoryApiConnectionWrapper_UnsecuredConnection=Connexion non s\u00E9curis\u00E9e
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
index 87842a5..a82cb5d 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
@@ -84,9 +84,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
     /** The URL simple constant */
     private static final String X_AUTH_METHOD_SIMPLE = "Simple"; //$NON-NLS-1$
 
-    /** The URL PLAIN constant */
-    private static final String X_AUTH_METHOD_PLAIN = "PLAIN"; //$NON-NLS-1$
-
     /** The URL DIGEST-MD5 constant */
     private static final String X_AUTH_METHOD_DIGEST_MD5 = "DIGEST-MD5"; //$NON-NLS-1$
 
@@ -145,9 +142,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
     /** The text widget to input bind password */
     private Text bindPasswordText;
 
-    /** The text widget to input the SASL PLAIN autzid (if selected) */
-    private Text authzidText;
-
     /** The checkbox to choose if the bind password should be saved on disk */
     private Button saveBindPasswordButton;
 
@@ -173,7 +167,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
     private Text krb5ConfigManualHostText;
     private Text krb5ConfigManualPortText;
 
-
     /**
      * Gets the authentication method.
      * 
@@ -223,17 +216,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
     }
 
 
-    /**
-     * Gets the bind authzid.
-     * 
-     * @return the authzid
-     */
-    private String getAuthzid()
-    {
-        return authzidText.getText();
-    }
-
-
     private String getSaslRealm()
     {
         return saslRealmText.getText();
@@ -378,10 +360,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
             ConnectionUIConstants.DIALOGSETTING_KEY_PRINCIPAL_HISTORY );
         bindPrincipalCombo = BaseWidgetUtils.createCombo( composite, dnHistory, -1, 2 );
 
-        BaseWidgetUtils.createLabel( composite, Messages.getString( "AuthenticationParameterPage.Authzid" ), 1 ); //$NON-NLS-1$
-        authzidText = BaseWidgetUtils.createText( composite, "SASL PLAIN only", 2 ); //$NON-NLS-1$
-        authzidText.setEnabled( false );
-
         BaseWidgetUtils.createLabel( composite, Messages.getString( "AuthenticationParameterPage.BindPassword" ), 1 ); //$NON-NLS-1$
         bindPasswordText = BaseWidgetUtils.createPasswordText( composite, StringUtils.EMPTY, 2 ); //$NON-NLS-1$
 
@@ -1031,10 +1009,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
     {
         switch ( parameter.getAuthMethod() )
         {
-            case SASL_PLAIN :
-                ldapUrl.getExtensions().add( new Extension( false, X_AUTH_METHOD, X_AUTH_METHOD_PLAIN ) );
-                break;
-                
             case SASL_CRAM_MD5:
                 ldapUrl.getExtensions().add( new Extension( false, X_AUTH_METHOD, X_AUTH_METHOD_CRAM_MD5 ) );
                 break;
@@ -1078,7 +1052,6 @@ public class AuthenticationParameterPage extends AbstractConnectionParameterPage
 
         switch ( parameter.getAuthMethod() )
         {
-            case SASL_PLAIN:
             case SASL_CRAM_MD5:
             case SASL_DIGEST_MD5:
             case SASL_GSSAPI:
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
index 4b6f2eb..b1e4831 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
@@ -59,13 +59,17 @@ public class ConnectionLabelProvider extends LabelProvider
         {
             Connection conn = ( Connection ) obj;
 
+            boolean isConnected = conn.getConnectionWrapper().isConnected();
+            boolean isSecured = conn.getConnectionWrapper().isSecured();
+            String unsecuredWarning = isConnected && !isSecured ? " UNSECURED! " : ""; //$NON-NLS-1$ //$NON-NLS-2$
+
             if ( conn.getEncryptionMethod() == EncryptionMethod.LDAPS )
             {
-                return conn.getName() + " (LDAPS)"; //$NON-NLS-1$
+                return conn.getName() + unsecuredWarning + " (LDAPS)"; //$NON-NLS-1$
             }
             else if ( conn.getEncryptionMethod() == EncryptionMethod.START_TLS )
             {
-                return conn.getName() + " (StartTLS)"; //$NON-NLS-1$
+                return conn.getName() + unsecuredWarning + " (StartTLS)"; //$NON-NLS-1$
             }
             else
             {
@@ -99,18 +103,21 @@ public class ConnectionLabelProvider extends LabelProvider
         {
             Connection conn = ( Connection ) obj;
 
-            if ( ( conn.getEncryptionMethod() == EncryptionMethod.LDAPS )
-                || ( conn.getEncryptionMethod() == EncryptionMethod.START_TLS ) )
+            boolean isConnected = conn.getConnectionWrapper().isConnected();
+            boolean isSecured = conn.getConnectionWrapper().isSecured();
+            boolean isEncryptionConfigured = conn.getEncryptionMethod().isEncrytped();
+
+            if ( isConnected )
             {
-                return conn.getConnectionWrapper().isConnected() ? ConnectionUIPlugin.getDefault().getImage(
+                return isSecured ? ConnectionUIPlugin.getDefault().getImage(
                     ConnectionUIConstants.IMG_CONNECTION_SSL_CONNECTED )
                     : ConnectionUIPlugin.getDefault().getImage(
-                        ConnectionUIConstants.IMG_CONNECTION_SSL_DISCONNECTED );
+                        ConnectionUIConstants.IMG_CONNECTION_CONNECTED );
             }
             else
             {
-                return conn.getConnectionWrapper().isConnected() ? ConnectionUIPlugin.getDefault().getImage(
-                    ConnectionUIConstants.IMG_CONNECTION_CONNECTED )
+                return isEncryptionConfigured ? ConnectionUIPlugin.getDefault().getImage(
+                    ConnectionUIConstants.IMG_CONNECTION_SSL_DISCONNECTED )
                     : ConnectionUIPlugin.getDefault().getImage(
                         ConnectionUIConstants.IMG_CONNECTION_DISCONNECTED );
             }
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
index 6ebf8fc..49000f2 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
@@ -44,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.net.ConnectException;
 import java.nio.channels.UnresolvedAddressException;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -66,6 +67,8 @@ import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyReq
 //import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponse;
 import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequest;
 import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+import org.apache.directory.api.ldap.model.constants.SaslQoP;
+import org.apache.directory.api.ldap.model.constants.SaslSecurityStrength;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.DefaultModification;
@@ -73,6 +76,7 @@ import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
+import org.apache.directory.api.ldap.model.exception.LdapAuthenticationNotSupportedException;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapLoopDetectedException;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -88,6 +92,7 @@ import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.ConnectionParameter;
 import org.apache.directory.studio.connection.core.ConnectionParameter.AuthenticationMethod;
 import org.apache.directory.studio.connection.core.ConnectionParameter.EncryptionMethod;
+import org.apache.directory.studio.connection.core.ICertificateHandler.TrustLevel;
 import org.apache.directory.studio.connection.core.IReferralHandler;
 import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
 import org.apache.directory.studio.connection.core.io.ConnectionWrapper;
@@ -99,9 +104,9 @@ import org.apache.directory.studio.ldapbrowser.core.jobs.InitializeRootDSERunnab
 import org.apache.directory.studio.ldapbrowser.core.model.impl.BrowserConnection;
 import org.apache.directory.studio.test.integration.junit5.LdapServerType;
 import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.directory.studio.test.integration.junit5.SkipTestIfLdapServerIsNotAvailableInterceptor;
 import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
-import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.mina.util.AvailablePortFinder;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.junit.jupiter.api.AfterAll;
@@ -128,6 +133,7 @@ public class DirectoryApiConnectionWrapperTest
     public static void suspendEventFiringInCurrentThread()
     {
         ConnectionEventRegistry.suspendEventFiringInCurrentThread();
+        ConnectionCorePlugin.getDefault().setCertificateHandler( null );
     }
 
 
@@ -149,29 +155,76 @@ public class DirectoryApiConnectionWrapperTest
 
 
     /**
-     * Tests connecting to the server.
+     * Tests connecting to the server without encryption.
      */
     @ParameterizedTest
-    @LdapServersSource
-    public void testConnect( TestLdapServer ldapServer )
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectPlain( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = getProgressMonitor();
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
-            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null, true, null,
-            30000L );
-        Connection connection = new Connection( connectionParameter );
-        ConnectionWrapper connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, null, null );
 
         assertFalse( connectionWrapper.isConnected() );
 
-        connectionWrapper.connect( monitor );
+        X509Certificate[] certificates = connectionWrapper.connect( monitor );
         assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
         assertNull( monitor.getException() );
+        assertNull( certificates );
 
         connectionWrapper.disconnect();
         assertFalse( connectionWrapper.isConnected() );
+    }
+
 
-        // TODO: SSL, StartTLS
+    /**
+     * Tests connecting to the server using ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectLdaps( TestLdapServer ldapServer )
+    {
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, null, null );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        X509Certificate[] certificates = connectionWrapper.connect( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+        assertNotNull( certificates );
+
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Tests connecting to the server using StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectStartTls( TestLdapServer ldapServer )
+    {
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, null, null );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        X509Certificate[] certificates = connectionWrapper.connect( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+        assertNotNull( certificates );
+
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
     }
 
 
@@ -179,21 +232,16 @@ public class DirectoryApiConnectionWrapperTest
      * Test failed connections to the server.
      */
     @ParameterizedTest
-    @LdapServersSource
+    @LdapServersSource(mode = Mode.All)
     public void testConnectFailures( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = null;
-        ConnectionParameter connectionParameter = null;
         Connection connection = null;
-        ConnectionWrapper connectionWrapper = null;
 
         // invalid port
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
-            AvailablePortFinder.getNextAvailable(), EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null,
-            true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        connection = getConnection( monitor, ldapServer, null, null );
+        connection.setPort( AvailablePortFinder.getNextAvailable() );
         connectionWrapper.connect( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
@@ -205,10 +253,8 @@ public class DirectoryApiConnectionWrapperTest
 
         // unknown host
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, "555.555.555.555", ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null, true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        connection = getConnection( monitor, ldapServer, null, null );
+        connection.setHost( "555.555.555.555" );
         connectionWrapper.connect( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
@@ -217,30 +263,222 @@ public class DirectoryApiConnectionWrapperTest
         assertTrue( monitor.getException().getCause() instanceof InvalidConnectionException );
         assertNotNull( monitor.getException().getCause().getCause() );
         assertTrue( monitor.getException().getCause().getCause() instanceof UnresolvedAddressException );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindPlain( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( false );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), ldapServer.getAdminPassword() );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
 
-        // TODO: SSL, StartTLS
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
     }
 
 
     /**
-     * Test binding to the server.
+     * Test binding to the server using simple auth and no encryption should fail if the server requires confidentially.
      */
     @ParameterizedTest
-    @LdapServersSource
-    public void testBind( TestLdapServer ldapServer )
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindPlainConfidentiallyRequired( TestLdapServer ldapServer )
     {
+        ldapServer.setConfidentialityRequired( true );
         StudioProgressMonitor monitor = getProgressMonitor();
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
-            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, ldapServer.getAdminDn(),
-            ldapServer.getAdminPassword(), null, true, null, 30000L );
-        Connection connection = new Connection( connectionParameter );
-        ConnectionWrapper connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), ldapServer.getAdminPassword() );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertFalse( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNotNull( monitor.getException() );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 13 - confidentialityRequired]" ) );
+        assertNotNull( monitor.getException().getCause() );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationNotSupportedException );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindLdaps( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindStartTls( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslBindPlain( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( false );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL and no encryption should fail if the server requires confidentially.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslBindPlainConfidentiallyRequired( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertFalse( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNotNull( monitor.getException() );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 13 - confidentialityRequired]" ) );
+        assertNotNull( monitor.getException().getCause() );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationNotSupportedException );
+    }
+
+
+    /**
+     * Test binding to the server using SASL and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslBindLdaps( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslBindStartTls( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+        acceptAllCertificates();
 
         assertFalse( connectionWrapper.isConnected() );
 
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
+
         assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
         assertNull( monitor.getException() );
 
         connectionWrapper.unbind();
@@ -257,17 +495,10 @@ public class DirectoryApiConnectionWrapperTest
     public void testBindFailures( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = null;
-        ConnectionParameter connectionParameter = null;
-        Connection connection = null;
-        ConnectionWrapper connectionWrapper = null;
 
         // simple auth with invalid user
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, ldapServer.getHost(), ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, "cn=invalid," + USERS_DN, "invalid", null, true,
-            null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, "cn=invalid," + USERS_DN, "invalid" );
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
         assertFalse( connectionWrapper.isConnected() );
@@ -283,11 +514,7 @@ public class DirectoryApiConnectionWrapperTest
 
         // simple auth with invalid password
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, ldapServer.getHost(), ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, ldapServer.getAdminDn(), "invalid", null, true, null,
-            30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), "invalid" );
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
         assertFalse( connectionWrapper.isConnected() );
@@ -1055,58 +1282,57 @@ public class DirectoryApiConnectionWrapperTest
     }
 
 
-    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer,
-        String dn, String password )
+    protected void acceptAllCertificates()
     {
-        // simple auth without principal and credential
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
-            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, dn, password, null, false, null,
-            30000L );
+        ConnectionCorePlugin.getDefault().setCertificateHandler( ( host, certChain, failCauses ) -> {
+            return TrustLevel.Permanent;
+        } );
+    }
 
-        Connection connection = new Connection( connectionParameter );
 
-        connectionWrapper = connection.getConnectionWrapper();
-        connectionWrapper.connect( monitor );
-        connectionWrapper.bind( monitor );
+    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer )
+    {
+        return getConnectionWrapper( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+    }
 
-        assertTrue( connectionWrapper.isConnected() );
 
-        IReferralHandler referralHandler = referralUrls -> {
-            return connection;
-        };
-        ConnectionCorePlugin.getDefault().setReferralHandler( referralHandler );
+    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer,
+        String dn, String password )
+    {
+        getConnection( monitor, ldapServer, dn, password );
 
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
         assertTrue( connectionWrapper.isConnected() );
         assertNull( monitor.getException() );
 
         return connectionWrapper;
+
     }
 
 
-    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer )
+    protected Connection getConnection( StudioProgressMonitor monitor, TestLdapServer ldapServer,
+        String dn, String password )
     {
         // simple auth without principal and credential
         ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
-            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, ldapServer.getAdminDn(),
-            ldapServer.getAdminPassword(), null, false, null, 30000L );
+            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, dn, password, null, false, null,
+            30000L );
+        connectionParameter.setSaslQop( SaslQoP.AUTH_CONF );
+        connectionParameter.setSaslSecurityStrength( SaslSecurityStrength.HIGH );
+        connectionParameter.setSaslMutualAuthentication( true );
 
         Connection connection = new Connection( connectionParameter );
 
-        connectionWrapper = connection.getConnectionWrapper();
-        connectionWrapper.connect( monitor );
-        connectionWrapper.bind( monitor );
-
-        assertTrue( connectionWrapper.isConnected() );
-
         IReferralHandler referralHandler = referralUrls -> {
             return connection;
         };
         ConnectionCorePlugin.getDefault().setReferralHandler( referralHandler );
 
-        assertTrue( connectionWrapper.isConnected() );
-        assertNull( monitor.getException() );
+        connectionWrapper = connection.getConnectionWrapper();
 
-        return connectionWrapper;
+        return connection;
     }
 
 }
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java
index ade8ddf..c93a945 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java
@@ -86,7 +86,7 @@ public class ApacheDirectoryServer extends TestLdapServer
             service.setInterceptors( service.getInterceptors().stream()
                 .filter( i -> !i.getName().equals( "ConfigurableHashingInterceptor" ) )
                 .collect( Collectors.toList() ) );
-            System.out.println( service.getInterceptors() );
+            service.setAllowAnonymousAccess( true );
 
             server = new LdapServer();
             server.setDirectoryService( service );
@@ -97,6 +97,7 @@ public class ApacheDirectoryServer extends TestLdapServer
             server.addTransports( ldaps );
 
             server.addSaslMechanismHandler( "SIMPLE", new SimpleMechanismHandler() );
+            server.addSaslMechanismHandler( "CRAM-MD5", new CramMd5MechanismHandler() );
             server.addSaslMechanismHandler( "DIGEST-MD5", new DigestMd5MechanismHandler() );
             server.setSaslRealms( Collections.singletonList( "EXAMPLE.ORG" ) );
             server.setSaslHost( getHost() );
@@ -153,6 +154,13 @@ public class ApacheDirectoryServer extends TestLdapServer
     }
 
 
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        server.setConfidentialityRequired( confidentialityRequired );
+    }
+
+
     private ApacheDirectoryServer( int port, int portSSL )
     {
         super( LdapServerType.ApacheDS, LOCALHOST, port, portSSL, "uid=admin,ou=system", "secret" );
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java
index b856ee5..7f8a0ac 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java
@@ -23,6 +23,10 @@ package org.apache.directory.studio.test.integration.junit5;
 
 import static org.apache.directory.studio.test.integration.junit5.Constants.LOCALHOST;
 
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+
 
 /**
  * An 389ds implementation of a test LDAP server.
@@ -52,4 +56,15 @@ public class Fedora389dsLdapServer extends TestLdapServer
             FEDORA_389DS_ADMIN_DN, FEDORA_389DS_ADMIN_PASSWORD );
     }
 
+
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        withAdminConnection( connection -> {
+            Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+                "nsslapd-require-secure-binds", confidentialityRequired ? "on" : "off" );
+            connection.modify( "cn=config", modification );
+        } );
+
+    }
 }
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java
index 23c6495..69b80cb 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java
@@ -23,10 +23,13 @@ package org.apache.directory.studio.test.integration.junit5;
 
 import static org.apache.directory.studio.test.integration.junit5.Constants.LOCALHOST;
 
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
 import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException;
 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
 import org.apache.directory.api.ldap.model.ldif.LdifReader;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.LdapConnection;
 
 
 /**
@@ -63,7 +66,7 @@ public class OpenLdapServer extends TestLdapServer
     {
         super.prepare();
 
-        try ( LdapNetworkConnection connection = new LdapNetworkConnection( OPENLDAP_HOST, OPENLDAP_PORT );
+        try ( LdapConnection connection = openConnection();
             LdifReader ldifReader = new LdifReader( TestFixture.class.getResourceAsStream( "OpenLdapConfig.ldif" ) ) )
         {
             connection.bind( OPENLDAP_CONFIG_DN, OPENLDAP_CONFIG_PASSWORD );
@@ -81,4 +84,25 @@ public class OpenLdapServer extends TestLdapServer
         }
     }
 
+
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        try ( LdapConnection connection = openConnection() )
+        {
+            connection.bind( OPENLDAP_CONFIG_DN, OPENLDAP_CONFIG_PASSWORD );
+            Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+                "olcSecurity", confidentialityRequired ? "ssf=256 tls=256" : "ssf=0 tls=0" );
+            connection.modify( "cn=config", modification );
+        }
+        catch ( LdapNoSuchAttributeException e )
+        {
+            // ignore
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+    }
+
 }
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java
index 9caa587..f0fe345 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java
@@ -26,7 +26,9 @@ import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
 import org.apache.directory.api.ldap.model.ldif.LdifReader;
 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.apache.directory.ldap.client.api.exception.InvalidConnectionException;
 
 
@@ -83,13 +85,25 @@ public abstract class TestLdapServer
 
     public LdapConnection openAdminConnection() throws LdapException
     {
-        LdapConnection connection = new LdapNetworkConnection( host, port );
-        connection.connect();
+        LdapConnection connection = openConnection();
         connection.bind( adminDn, adminPassword );
         return connection;
     }
 
 
+    public LdapConnection openConnection() throws LdapException
+    {
+        LdapConnectionConfig config = new LdapConnectionConfig();
+        config.setLdapHost( host );
+        config.setLdapPort( port );
+        config.setUseTls( true );
+        config.setTrustManagers( new NoVerificationTrustManager() );
+        LdapConnection connection = new LdapNetworkConnection( config );
+        connection.connect();
+        return connection;
+    }
+
+
     public void withAdminConnection( LdapConnectionConsumer consumer )
     {
         try ( LdapConnection connection = openAdminConnection() )
@@ -129,6 +143,7 @@ public abstract class TestLdapServer
         TestFixture.createContextEntry( this );
         TestFixture.cleanup( this );
         TestFixture.importData( this );
+        setConfidentialityRequired( false );
 
         String serverSpecificLdif = getType().name() + ".ldif";
         if ( TestFixture.class.getResource( serverSpecificLdif ) != null )
@@ -200,6 +215,9 @@ public abstract class TestLdapServer
     }
 
 
+    public abstract void setConfidentialityRequired( boolean confidentialityRequired );
+
+
     @Override
     public String toString()
     {
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif
index 9fe06a5..158317f 100644
--- a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif
+++ b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif
@@ -36,8 +36,9 @@ dn: cn=config
 changetype: modify
 replace: olcAuthzRegexp
 olcAuthzRegexp: uid=([^,]*),cn=digest-md5,cn=auth uid=$1,ou=users,dc=example,dc=org
+olcAuthzRegexp: uid=([^,]*),cn=cram-md5,cn=auth uid=$1,ou=users,dc=example,dc=org
 -
 replace: olcSaslSecProps
-olcSaslSecProps: noplain,noanonymous,minssf=128
+olcSaslSecProps: noplain,noanonymous,minssf=0
 -
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java
index b59294b..817847f 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java
@@ -23,6 +23,7 @@ package org.apache.directory.studio.test.integration.ui;
 import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
 import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRALS_DN;
 
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -30,6 +31,7 @@ import java.util.List;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.test.integration.junit5.SkipTestIfLdapServerIsNotAvailableInterceptor;
 import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.ApacheDSServersViewBot;
@@ -76,6 +78,20 @@ public class AbstractTestBase
     @AfterEach
     final void tearDownBase() throws Exception
     {
+        // clear custom trust stores
+        X509Certificate[] permanentCertificates = ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager()
+            .getCertificates();
+        for ( X509Certificate certificate : permanentCertificates )
+        {
+            ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager().removeCertificate( certificate );
+        }
+        X509Certificate[] temporaryCertificates = ConnectionCorePlugin.getDefault().getSessionTrustStoreManager()
+            .getCertificates();
+        for ( X509Certificate certificate : temporaryCertificates )
+        {
+            ConnectionCorePlugin.getDefault().getSessionTrustStoreManager().removeCertificate( certificate );
+        }
+
         connectionsViewBot.deleteTestConnections();
         serversViewBot.deleteTestServers();
         Assertions.genericTearDownAssertions();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
index a78b757..54b555c 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
@@ -107,20 +107,6 @@ public class CertificateValidationTest extends AbstractTestBase
     @AfterEach
     public void tearDown() throws Exception
     {
-        // delete custom trust stores
-        X509Certificate[] permanentCertificates = ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager()
-            .getCertificates();
-        for ( X509Certificate certificate : permanentCertificates )
-        {
-            ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager().removeCertificate( certificate );
-        }
-        X509Certificate[] temporaryCertificates = ConnectionCorePlugin.getDefault().getSessionTrustStoreManager()
-            .getCertificates();
-        for ( X509Certificate certificate : temporaryCertificates )
-        {
-            ConnectionCorePlugin.getDefault().getSessionTrustStoreManager().removeCertificate( certificate );
-        }
-
         // delete custom Java key store settings
         System.clearProperty( "javax.net.ssl.trustStore" );
         System.clearProperty( "javax.net.ssl.trustStorePassword" );
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
index 93df03f..2fcba85 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
@@ -21,7 +21,6 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.hamcrest.CoreMatchers.anyOf;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -40,11 +39,13 @@ import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.ConnectionManager;
 import org.apache.directory.studio.connection.core.ConnectionParameter.AuthenticationMethod;
-import org.apache.directory.studio.test.integration.junit5.Constants;
+import org.apache.directory.studio.connection.core.ConnectionParameter.EncryptionMethod;
 import org.apache.directory.studio.test.integration.junit5.LdapServerType;
 import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
 import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.CertificateTrustDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewConnectionWizardBot;
 import org.apache.mina.util.AvailablePortFinder;
 import org.junit.jupiter.api.BeforeEach;
@@ -342,18 +343,57 @@ public class NewConnectionWizardTest extends AbstractTestBase
     }
 
 
-    /**
-     * Creates a new connection using the new connection wizard.
-     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionNoEncryptionNoAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.NONE, "", "" );
+    }
+
+
     @ParameterizedTest
     @LdapServersSource
-    public void testCreateConnection( TestLdapServer server )
+    public void testCreateConnectionNoEncryptionNoAuthInvalidHostname( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.clickBackButton();
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        wizardBot.clickNextButton();
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnectionError( hostname );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionNoEncryptionSimpleAuthOK( TestLdapServer server ) throws UnknownHostException
     {
         // enter connection parameter
         wizardBot.typeConnectionName( getConnectionName() );
         wizardBot.typeHost( server.getHost() );
         wizardBot.typePort( server.getPort() );
 
+        // click "Check Network Parameter" button
+        String result = wizardBot.clickCheckNetworkParameterButton();
+        assertNull( result, "Expected OK" );
+
+        // enter IPv4 address as host
+        wizardBot.typeHost( InetAddress.getByName( server.getHost() ).getHostAddress() );
+
+        // click "Check Network Parameter" button
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertNull( result, "Expected OK" );
+
+        // enter hostname as host again
+        wizardBot.typeHost( server.getHost() );
+
         // jump to auth page
         wizardBot.clickNextButton();
 
@@ -361,261 +401,470 @@ public class NewConnectionWizardTest extends AbstractTestBase
         wizardBot.typeUser( server.getAdminDn() );
         wizardBot.typePassword( server.getAdminPassword() );
 
-        // finish dialog
-        wizardBot.clickFinishButton( true );
-        connectionsViewBot.waitForConnection( getConnectionName() );
-
-        // ensure connection was created
-        ConnectionManager connectionManager = ConnectionCorePlugin.getDefault().getConnectionManager();
-        assertNotNull( connectionManager.getConnections() );
-        assertEquals( 1, connectionManager.getConnections().length );
-        Connection connection = connectionManager.getConnections()[0];
-        assertEquals( getConnectionName(), connection.getName() );
-        assertEquals( server.getHost(), connection.getHost() );
-        assertEquals( server.getPort(), connection.getPort() );
-        assertEquals( AuthenticationMethod.SIMPLE, connection.getAuthMethod() );
-        assertEquals( server.getAdminDn(), connection.getBindPrincipal() );
-        assertEquals( server.getAdminPassword(), connection.getBindPassword() );
-
-        // ensure connection is visible in Connections view
-        assertEquals( 1, connectionsViewBot.getCount() );
+        // click "Check Network Parameter" button
+        result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
 
-        // close connection
-        connectionsViewBot.closeSelectedConnections();
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
     }
 
 
-    /**
-     * Tests the "Check Network Parameter" button.
-     */
     @ParameterizedTest
-    @LdapServersSource
-    public void testCheckNetworkParameterButtonOK( TestLdapServer server ) throws UnknownHostException
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionNoEncryptionSimpleAuthConfidentialityRequired( TestLdapServer server )
+
     {
-        // enter connection parameter with host name
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
+        setConnectionParameters( server, EncryptionMethod.NONE );
 
-        // click "Check Network Parameter" button
-        String result1 = wizardBot.clickCheckNetworkParameterButton();
-        assertNull( result1, "Expected OK" );
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
 
-        // enter connection parameter with IPv4 address
-        wizardBot.typeHost( InetAddress.getByName( server.getHost() ).getHostAddress() );
-        wizardBot.typePort( server.getPort() );
+        server.setConfidentialityRequired( true );
 
-        // click "Check Network Parameter" button
-        String result2 = wizardBot.clickCheckNetworkParameterButton();
-        assertNull( result2, "Expected OK" );
-
-        //
-        // Don't know why this doesn't work with SWTBot.
-        // When testing manually it works.
-        //
-        // // enter connection parameter with IPv6 address
-        // wizardBot.typeHost( "[::1]" );
-        // wizardBot.typePort( ldapService.getPort() );
-        //
-        // // click "Check Network Parameter" button
-        // String result3 = wizardBot.clickCheckNetworkParameterButton();
-        // assertNull( "Expected OK", result3 );
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 13 - confidentialityRequired]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 13 - confidentialityRequired]" );
 
-        wizardBot.clickCancelButton();
     }
 
 
-    /**
-     * Tests the "Check Network Parameter" button.
-     */
-    @Test
-    public void testCheckNetworkParameterButtonNotOK()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionNoEncryptionSaslCramMd5OK( TestLdapServer server )
     {
-        // enter connection parameter with invalid port
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( Constants.LOCALHOST );
-        wizardBot.typePort( AvailablePortFinder.getNextAvailable( 1024 ) );
-
-        // click "Check Network Parameter" button and get the result
-        String result1 = wizardBot.clickCheckNetworkParameterButton();
-        assertNotNull( result1 );
-        // LDAP API: Connection refused
-        // JNDI: The connection failed
-        assertThat( result1,
-            anyOf( containsString( "Connection refused" ), containsString( "The connection failed" ) ) );
-
-        // enter connection parameter with invalid host name
-        String hostname = "qwertzuiop.asdfghjkl.yxcvbnm";
-        wizardBot.typeHost( hostname );
-        wizardBot.typePort( 389 );
+        setConnectionParameters( server, EncryptionMethod.NONE );
 
-        // click "Check Network Parameter" button and get the result
-        String result2 = wizardBot.clickCheckNetworkParameterButton();
-        assertNotNull( "Expected Error", result2 );
-        // LDAP API: could not be resolved
-        // JNDI: The connection failed
-        assertThat( result2,
-            anyOf( containsString( "could not be resolved" ), containsString( "The connection failed" ) ) );
-        assertThat( "Unknown host name must occur in error message", result2, containsString( hostname ) );
-
-        // disabled this test because it does not work properly
-        // as it depends from the network connection settings.
-        //        // enter connection parameter with non-routed IP address
-        //        String ipAddress = "10.11.12.13";
-        //        wizardBot.typeHost( ipAddress );
-        //        wizardBot.typePort( ldapServer.getPort() );
-        //
-        //        // click "Check Network Parameter" button and get the result
-        //        String result3 = wizardBot.clickCheckNetworkParameterButton();
-        //        assertNotNull( "Expected Error", result3 );
-        //        assertTrue( "'No route to host' or 'Network is unreachable' message must occur in error message", //
-        //            result3.contains( "No route to host" ) || result3.contains( "Network is unreachable" ) );
-        //        assertTrue( "IP address must occur in error message", result3.contains( ipAddress ) );
+        wizardBot.selectCramMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
 
-        wizardBot.clickCancelButton();
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_CRAM_MD5,
+            "user.1", "password" );
     }
 
 
-    /**
-     * Tests the "Check Authentication" button.
-     */
     @ParameterizedTest
-    @LdapServersSource
-    public void testCheckAuthenticationButtonSimpleAuthOK( TestLdapServer server )
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionNoEncryptionSaslDigestMd5OK( TestLdapServer server )
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
-        wizardBot.clickNextButton();
+        setConnectionParameters( server, EncryptionMethod.NONE );
 
-        // enter correct authentication parameter
-        wizardBot.typeUser( server.getAdminDn() );
-        wizardBot.typePassword( server.getAdminPassword() );
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
 
-        // click "Check Network Parameter" button
         String result = wizardBot.clickCheckAuthenticationButton();
         assertNull( result, "Expected OK" );
 
-        wizardBot.clickCancelButton();
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
     }
 
 
-    /**
-     * Tests the "Check Authentication" button.
-     */
     @ParameterizedTest
-    @LdapServersSource
-    public void testCheckAuthenticationButtonSimpleAuthNotOK( TestLdapServer server )
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionNoEncryptionSaslDigestMd5ConfidentialityRequired( TestLdapServer server )
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
-        wizardBot.clickNextButton();
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        server.setConfidentialityRequired( true );
+
+        finishAndAssertConnectionError( "[LDAP result code 13 - confidentialityRequired]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionNoAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.NONE, "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionSimpleAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
 
-        // enter incorrect authentication parameter
         wizardBot.typeUser( server.getAdminDn() );
-        wizardBot.typePassword( "secret45" );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionSimpleAuthInvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( "cn=invalid" );
+        wizardBot.typePassword( "invalid" );
 
-        // click "Check Network Parameter" button
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNotNull( result );
         assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
 
-        wizardBot.clickCancelButton();
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
     }
 
 
-    /**
-     * Tests the "Check Authentication" button.
-     */
     @ParameterizedTest
-    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
-    public void testCheckAuthenticationButtonDigestMD5OK( TestLdapServer server )
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5Ok( TestLdapServer server )
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
-        wizardBot.clickNextButton();
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
 
-        // enter correct authentication parameter
         wizardBot.selectDigestMD5Authentication();
-        wizardBot.typeUser( "user.8" );
+        wizardBot.typeUser( "user.1" );
         wizardBot.typePassword( "password" );
         if ( server.getType() == LdapServerType.ApacheDS )
         {
             wizardBot.typeRealm( "EXAMPLE.ORG" );
         }
-        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5InvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "invalid" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
         wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
 
-        // click "Check Network Parameter" button
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( result, "Expected OK" );
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
 
-        wizardBot.clickCancelButton();
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
     }
 
 
-    /**
-     * Tests the "Check Authentication" button.
-     */
     @ParameterizedTest
-    @LdapServersSource(only = LdapServerType.OpenLdap)
-    public void testCheckAuthenticationButtonDigestMD5OKTooWeek( TestLdapServer server )
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5InvalidRealm( TestLdapServer server )
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
-        wizardBot.clickNextButton();
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
 
-        // enter correct authentication parameter
         wizardBot.selectDigestMD5Authentication();
-        wizardBot.typeUser( "user.8" );
+        wizardBot.typeUser( "user.1" );
         wizardBot.typePassword( "password" );
+        wizardBot.typeRealm( "APACHE.ORG" );
         wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
-        wizardBot.selectProtectionStrength( SaslSecurityStrength.LOW );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
 
-        // click "Check Network Parameter" button
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertThat( result, containsString( "DIGEST-MD5: No common protection layer between client and server" ) );
+        assertThat( result, containsString( "[LDAP result code" ) );
 
-        wizardBot.clickCancelButton();
+        finishAndAssertConnectionError( "[LDAP result code" );
     }
 
 
-    /**
-     * Tests the "Check Authentication" button.
-     */
     @ParameterizedTest
-    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
-    public void testCheckAuthenticationButtonDigestMD5NotOKWrongPassword( TestLdapServer server )
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionStartTlsEncryptionNoAuthOK( TestLdapServer server )
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( server.getHost() );
-        wizardBot.typePort( server.getPort() );
-        wizardBot.clickNextButton();
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.NONE, "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionStartTlsEncryptionSimpleAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionStartTlsEncryptionSimpleAuthInvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( "cn=invalid" );
+        wizardBot.typePassword( "invalid" );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionStartTlsEncryptionSaslDigestMd5OK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
 
-        // enter correct authentication parameter
         wizardBot.selectDigestMD5Authentication();
-        wizardBot.typeUser( "user.8" );
-        wizardBot.typePassword( "wrong" );
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
         if ( server.getType() == LdapServerType.ApacheDS )
         {
             wizardBot.typeRealm( "EXAMPLE.ORG" );
         }
-        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "SASL not configured for 389ds")
+    public void testCreateConnectionStartTlsEncryptionSaslDigestMd5InvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "invalid" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
         wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
 
-        // click "Check Network Parameter" button
         String result = wizardBot.clickCheckAuthenticationButton();
         assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
 
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCheckNetworkParameterButtonNoEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        String result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", result, containsString( hostname ) );
+
+        wizardBot.clickCancelButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCheckNetworkParameterButtonLdapsEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        String result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+
+        // Non ldaps port
+        wizardBot.typePort( server.getPort() );
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", result, containsString( hostname ) );
+
+        wizardBot.clickCancelButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCheckNetworkParameterButtonStartTlsEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        String result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+
+        // Ldaps port
+        wizardBot.typePort( server.getPortSSL() );
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        result = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( result, containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", result, containsString( hostname ) );
+
         wizardBot.clickCancelButton();
     }
 
+
+    private void setConnectionParameters( TestLdapServer server, EncryptionMethod encryptionMethod )
+    {
+        wizardBot.typeConnectionName( getConnectionName() );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( encryptionMethod == EncryptionMethod.LDAPS ? server.getPortSSL() : server.getPort() );
+
+        if ( encryptionMethod == EncryptionMethod.LDAPS )
+        {
+            wizardBot.selectLdapsEncryption();
+        }
+        if ( encryptionMethod == EncryptionMethod.START_TLS )
+        {
+            wizardBot.selectStartTlsEncryption();
+        }
+
+        if ( encryptionMethod != EncryptionMethod.NONE )
+        {
+            server.setConfidentialityRequired( true );
+            CertificateTrustDialogBot trustDialog = wizardBot
+                .clickCheckNetworkParameterButtonExpectingCertificateTrustDialog();
+            trustDialog.selectTrustPermanent();
+            trustDialog.clickOkButton();
+            bot.button( "OK" ).click();
+        }
+
+        wizardBot.clickNextButton();
+    }
+
+
+    private void finishAndAssertConnection( TestLdapServer server, EncryptionMethod encryptionMethod,
+        AuthenticationMethod authenticationMethod, String user, String password )
+    {
+        wizardBot.clickFinishButton( true );
+
+        connectionsViewBot.waitForConnection( getConnectionName() );
+
+        // ensure connection was created
+        ConnectionManager connectionManager = ConnectionCorePlugin.getDefault().getConnectionManager();
+        assertNotNull( connectionManager.getConnections() );
+        assertEquals( 1, connectionManager.getConnections().length );
+        Connection connection = connectionManager.getConnections()[0];
+        assertEquals( getConnectionName(), connection.getName() );
+        assertEquals( server.getHost(), connection.getHost() );
+        assertEquals( encryptionMethod == EncryptionMethod.LDAPS ? server.getPortSSL() : server.getPort(),
+            connection.getPort() );
+        assertEquals( user, connection.getBindPrincipal() );
+        assertEquals( password, connection.getBindPassword() );
+        assertEquals( authenticationMethod, connection.getAuthMethod() );
+        assertTrue( connection.getConnectionWrapper().isConnected() );
+        if ( encryptionMethod == EncryptionMethod.NONE )
+        {
+            assertFalse( connection.getConnectionWrapper().isSecured() );
+        }
+        else
+        {
+            assertTrue( connection.getConnectionWrapper().isSecured() );
+        }
+
+        // ensure connection is visible in Connections view
+        assertEquals( 1, connectionsViewBot.getCount() );
+
+        // close connection
+        connectionsViewBot.closeSelectedConnections();
+    }
+
+
+    private void finishAndAssertConnectionError( String errorText )
+    {
+        ErrorDialogBot errorBot = wizardBot.clickFinishButtonExpectingError();
+
+        String errorMessage = errorBot.getErrorMessage();
+        String errorDetails = errorBot.getErrorDetails();
+        assertNotNull( errorMessage );
+        assertNotNull( errorDetails );
+        assertThat( errorDetails, containsString( errorText ) );
+        errorBot.clickOkButton();
+
+        ConnectionManager connectionManager = ConnectionCorePlugin.getDefault().getConnectionManager();
+        assertNotNull( connectionManager.getConnections() );
+        assertEquals( 1, connectionManager.getConnections().length );
+        Connection connection = connectionManager.getConnections()[0];
+        assertEquals( getConnectionName(), connection.getName() );
+        assertFalse( connection.getConnectionWrapper().isConnected() );
+        assertFalse( connection.getConnectionWrapper().isSecured() );
+
+        // ensure connection is visible in Connections view
+        assertEquals( 1, connectionsViewBot.getCount() );
+    }
+
+
+    private int getInvalidPort()
+    {
+        return AvailablePortFinder.getNextAvailable( 1025 );
+    }
+
+
+    private static String getInvalidHostName()
+    {
+        return "qwertzuiop.asdfghjkl.yxcvbnm";
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
index 28b8a5f..332bd91 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
@@ -94,6 +94,13 @@ public abstract class WizardBot extends DialogBot
     }
 
 
+    public ErrorDialogBot clickFinishButtonExpectingError()
+    {
+        String shellText = BotUtils.shell( () -> clickFinishButton(), "Error", "Problem Occurred" ).getText();
+        return new ErrorDialogBot( shellText );
+    }
+
+
     public boolean existsCategory( String category )
     {
         TreeBot treeBot = new TreeBot( bot.tree() );

Mime
View raw message