You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2026/04/28 04:43:44 UTC

(directory-server) 01/01: Removing strict trust verification setting

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch coheigea/ldap-trust-manager-changes
in repository https://gitbox.apache.org/repos/asf/directory-server.git

commit 4ede73a3cc34bb66c0e10d876586648d1e283073
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Tue Apr 28 05:43:08 2026 +0100

    Removing strict trust verification setting
---
 .../ldap/replication/SyncReplConfiguration.java    |  57 +++++----
 .../server/annotations/CreateConsumer.java         |  13 +-
 .../server/factory/ServerAnnotationProcessor.java  |   6 +-
 .../server/config/beans/ReplConsumerBean.java      |  20 +--
 .../server/NoVerificationTrustManager.java         | 142 +++++++++++++++++++++
 .../ClientCertificateAuthenticationIT.java         |   2 +-
 .../server/operations/bind/SaslBindIT.java         |   4 +-
 .../apache/directory/server/ssl/KeyStoreIT.java    |   2 +-
 .../server/config/builder/ServiceBuilder.java      |   6 +-
 9 files changed, 203 insertions(+), 49 deletions(-)

diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConfiguration.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConfiguration.java
index 7634b6248a..b9164faa72 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConfiguration.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/SyncReplConfiguration.java
@@ -21,6 +21,7 @@ package org.apache.directory.server.ldap.replication;
 
 
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
 
 import javax.net.ssl.X509TrustManager;
@@ -31,7 +32,6 @@ import org.apache.directory.api.ldap.model.message.AliasDerefMode;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Network;
-import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
 
 
 /**
@@ -56,8 +56,7 @@ import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
  *   <li>chaseReferrals : tells if we chase referrals, defaults to false</li>
  *   <li>cookie : the replication cookie</li>
  *   <li>useTls : the connection uses TLS, defaults to true</li>
- *   <li>strictCertVerification : strictly verify the certificate, defaults to true</li>
- *   <li>trustManager : the trustManager to use, defaults to @link{ReplicationTrustManager}</li>
+ *   <li>trustManager : the trustManager to use, defaults to {@link ReplicationTrustManager}</li>
  *   <li></li>
  * </ul>
  * 
@@ -124,9 +123,6 @@ public class SyncReplConfiguration implements ReplicationConsumerConfig
     /** flag to indicate the use of TLS, default is true */
     private boolean useTls = true;
 
-    /** flag to indicate the use of strict certificate verification, default is true */
-    private boolean strictCertVerification = true;
-
     /** the X509 certificate trust manager used, default value set to {@link ReplicationTrustManager} */
     private X509TrustManager trustManager = ReplicationTrustManager.getInstance();
 
@@ -514,40 +510,52 @@ public class SyncReplConfiguration implements ReplicationConsumerConfig
 
 
     /**
-     * @return true if the certificate verification is enforced 
+     * @return The Trustmanager instance
      */
-    public boolean isStrictCertVerification()
+    public X509TrustManager getTrustManager()
     {
-        return strictCertVerification;
+        return trustManager;
     }
 
 
     /**
-     * set the strict certificate verification
-     * 
-     * @param strictCertVerification If we require a certificate validation
+     * Creates an X509 trust manager from the given fully-qualified class name.
+     *
+     * @param trustManagerFqcn The trust manager class name to instantiate
+     * @return The instantiated trust manager
      */
-    public void setStrictCertVerification( boolean strictCertVerification )
+    public static X509TrustManager createTrustManager( String trustManagerFqcn )
     {
-        if ( strictCertVerification )
+        try
         {
-            trustManager = ReplicationTrustManager.getInstance();
+            Class<?> trustManagerClass = Class.forName( trustManagerFqcn );
+
+            if ( !X509TrustManager.class.isAssignableFrom( trustManagerClass ) )
+            {
+                throw new IllegalArgumentException( "class " + trustManagerFqcn + " is not an X509TrustManager" );
+            }
+
+            return ( X509TrustManager ) trustManagerClass.newInstance();
         }
-        else
+        catch ( IllegalArgumentException iae )
         {
-            trustManager = new NoVerificationTrustManager();
+            throw iae;
+        }
+        catch ( Exception e )
+        {
+            throw new IllegalArgumentException( "Cannot instantiate trust manager class " + trustManagerFqcn, e );
         }
-
-        this.strictCertVerification = strictCertVerification;
     }
 
 
     /**
-     * @return The Trustmanager instance
+     * Sets the trust manager used for TLS certificate validation.
+     *
+     * @param trustManager The trust manager to use, cannot be null
      */
-    public X509TrustManager getTrustManager()
+    public void setTrustManager( X509TrustManager trustManager )
     {
-        return trustManager;
+        this.trustManager = Objects.requireNonNull( trustManager, "trustManager cannot be null" );
     }
 
 
@@ -636,11 +644,6 @@ public class SyncReplConfiguration implements ReplicationConsumerConfig
         sb.append( "provider:" ).append( producer ).append( ", " );
         sb.append( "user:'" ).append( replUserDn ).append( "', " );
 
-        if ( strictCertVerification )
-        {
-            sb.append( "strict" ).append( ", " );
-        }
-
         sb.append( "TLS:" ).append( useTls ).append( "]" );
 
         return sb.toString();
diff --git a/server-annotations/src/main/java/org/apache/directory/server/annotations/CreateConsumer.java b/server-annotations/src/main/java/org/apache/directory/server/annotations/CreateConsumer.java
index c01beefd45..40d8d03238 100644
--- a/server-annotations/src/main/java/org/apache/directory/server/annotations/CreateConsumer.java
+++ b/server-annotations/src/main/java/org/apache/directory/server/annotations/CreateConsumer.java
@@ -53,7 +53,7 @@ import org.apache.directory.api.ldap.model.message.SearchScope;
  *   <li>configEntryDn : the configuration entry's DN</li>
  *   <li>chaseReferrals : tells if we chase referrals, defaults to false</li>
  *   <li>useTls : the connection uses TLS, defaults to true</li>
- *   <li>strictCertVerification : strictly verify the certificate, defaults to true</li>
+ *   <li>trustManagerFQCN : X509TrustManager FQCN to override strictCertVerification</li>
  * </ul>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -199,11 +199,12 @@ public @interface CreateConsumer
     boolean useTls() default true;
 
 
-    /** 
-     * flag to indicate the use of strict certificate verification, default is true
-     *  
-     * @return <tt>true</tt> if a strict certificate validation is done
+    /**
+     * Fully-qualified class name of an X509TrustManager to use for replication TLS.
+     * If set, this takes precedence over strictCertVerification().
+     *
+     * @return The trust manager FQCN
      */
-    boolean strictCertVerification() default true;
+    String trustManagerFQCN() default "";
 
 }
diff --git a/server-annotations/src/main/java/org/apache/directory/server/factory/ServerAnnotationProcessor.java b/server-annotations/src/main/java/org/apache/directory/server/factory/ServerAnnotationProcessor.java
index 0d3aa460af..fbf1ab2d1f 100644
--- a/server-annotations/src/main/java/org/apache/directory/server/factory/ServerAnnotationProcessor.java
+++ b/server-annotations/src/main/java/org/apache/directory/server/factory/ServerAnnotationProcessor.java
@@ -296,7 +296,11 @@ public final class ServerAnnotationProcessor
         config.setUseTls( createConsumer.useTls() );
         config.setBaseDn( createConsumer.baseDn() );
         config.setRefreshInterval( createConsumer.refreshInterval() );
-        config.setStrictCertVerification( createConsumer.strictCertVerification() );
+
+        if ( !Strings.isEmpty( createConsumer.trustManagerFQCN() ) )
+        {
+            config.setTrustManager( SyncReplConfiguration.createTrustManager( createConsumer.trustManagerFQCN() ) );
+        }
 
         consumer.setConfig( config );
 
diff --git a/server-config/src/main/java/org/apache/directory/server/config/beans/ReplConsumerBean.java b/server-config/src/main/java/org/apache/directory/server/config/beans/ReplConsumerBean.java
index 9434a19a08..20f66c5ef9 100644
--- a/server-config/src/main/java/org/apache/directory/server/config/beans/ReplConsumerBean.java
+++ b/server-config/src/main/java/org/apache/directory/server/config/beans/ReplConsumerBean.java
@@ -98,9 +98,9 @@ public class ReplConsumerBean extends AdsBaseBean
     @ConfigurationElement(attributeType = SchemaConstants.ADS_REPL_USE_TLS, isOptional = true)
     private boolean replUseTls;
 
-    /** Tells if the certificate validation should be strict or not */
-    @ConfigurationElement(attributeType = SchemaConstants.ADS_REPL_STRICT_CERT_VALIDATION, isOptional = true)
-    private boolean replStrictCertValidation;
+    /** The X509 TrustManager FQCN to use */
+    @ConfigurationElement(attributeType = "ads-replTrustManagerFQCN", isOptional = true)
+    private String replTrustManagerFQCN;
 
     /** The FQCN of replication client implementation */
     @ConfigurationElement(attributeType = SchemaConstants.ADS_REPL_CONSUMER_IMPL, isOptional = true)
@@ -420,20 +420,20 @@ public class ReplConsumerBean extends AdsBaseBean
 
 
     /**
-     * @return the replStrictCertValidation
+     * @return the replTrustManagerFQCN
      */
-    public boolean isReplStrictCertValidation()
+    public String getReplTrustManagerFQCN()
     {
-        return replStrictCertValidation;
+        return replTrustManagerFQCN;
     }
 
 
     /**
-     * @param replStrictCertValidation the replStrictCertValidation to set
+     * @param replTrustManagerFQCN the replTrustManagerFQCN to set
      */
-    public void setReplStrictCertValidation( boolean replStrictCertValidation )
+    public void setReplTrustManagerFQCN( String replTrustManagerFQCN )
     {
-        this.replStrictCertValidation = replStrictCertValidation;
+        this.replTrustManagerFQCN = replTrustManagerFQCN;
     }
 
 
@@ -482,8 +482,8 @@ public class ReplConsumerBean extends AdsBaseBean
         sb.append( toString( tabs, "  user password", String.valueOf( replUserPassword ) ) ); // do not reveal the password, just null or not
         sb.append( toString( tabs, "  cookie", replCookie ) );
         sb.append( tabs ).append( "  consumer implementation's FQCN : " ).append( replConsumerImpl ).append( '\n' );
+        sb.append( toString( tabs, "  trust manager's FQCN", replTrustManagerFQCN ) );
 
-        sb.append( toString( tabs, "  struct certivicate validation", replStrictCertValidation ) );
         sb.append( toString( tabs, "  use TLS", replUseTls ) );
 
         return sb.toString();
diff --git a/server-integ/src/test/java/org/apache/directory/server/NoVerificationTrustManager.java b/server-integ/src/test/java/org/apache/directory/server/NoVerificationTrustManager.java
new file mode 100644
index 0000000000..59d7ac21c5
--- /dev/null
+++ b/server-integ/src/test/java/org/apache/directory/server/NoVerificationTrustManager.java
@@ -0,0 +1,142 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.server;
+
+
+import java.net.Socket;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509ExtendedTrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.directory.api.i18n.I18n;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * An implementation of {@link X509TrustManager} which trusts the given certificates without verifying them.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class NoVerificationTrustManager extends X509ExtendedTrustManager
+{
+    /** The logger. */
+    private static final Logger LOG = LoggerFactory.getLogger( NoVerificationTrustManager.class );
+    
+    
+    /**
+     * A public constructor
+     */
+    public NoVerificationTrustManager()
+    {
+        super();
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkClientTrusted( X509Certificate[] x509Certificates, String authType, Socket socket )
+        throws CertificateException 
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04168_CHECK_CLIENT_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkClientTrusted( X509Certificate[] x509Certificates, String authType, SSLEngine engine )
+        throws CertificateException 
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04168_CHECK_CLIENT_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+    
+    
+    public void checkServerTrusted( X509Certificate[] x509Certificates, String authType, Socket socket )
+        throws CertificateException 
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04169_CHECK_SERVER_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkServerTrusted( X509Certificate[] x509Certificates, String authType, SSLEngine engine )
+        throws CertificateException 
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04169_CHECK_SERVER_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkClientTrusted( X509Certificate[] x509Certificates, String s ) throws CertificateException
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04168_CHECK_CLIENT_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkServerTrusted( X509Certificate[] x509Certificates, String s ) throws CertificateException
+    {
+        if ( LOG.isDebugEnabled() )
+        {
+            LOG.debug( I18n.msg( I18n.MSG_04169_CHECK_SERVER_TRUSTED, x509Certificates[0] ) );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public X509Certificate[] getAcceptedIssuers()
+    {
+        return new X509Certificate[0];
+    }
+}
diff --git a/server-integ/src/test/java/org/apache/directory/server/ldap/handlers/sasl/external/ClientCertificateAuthenticationIT.java b/server-integ/src/test/java/org/apache/directory/server/ldap/handlers/sasl/external/ClientCertificateAuthenticationIT.java
index aba0507fe8..86a96e0d98 100644
--- a/server-integ/src/test/java/org/apache/directory/server/ldap/handlers/sasl/external/ClientCertificateAuthenticationIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/ldap/handlers/sasl/external/ClientCertificateAuthenticationIT.java
@@ -100,7 +100,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
                 },
         trustManagers =
                 {
-                        org.apache.directory.ldap.client.api.NoVerificationTrustManager.class
+                        org.apache.directory.server.NoVerificationTrustManager.class
                 },
         searchBaseDn = "ou=users,dc=example,dc=com")
 @ApplyLdifs(
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/bind/SaslBindIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/bind/SaslBindIT.java
index b79b627d64..244149fb38 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/bind/SaslBindIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/bind/SaslBindIT.java
@@ -64,10 +64,10 @@ import org.apache.directory.api.util.Network;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
-import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
 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.server.NoVerificationTrustManager;
 import org.apache.directory.server.annotations.CreateLdapServer;
 import org.apache.directory.server.annotations.CreateTransport;
 import org.apache.directory.server.annotations.SaslMechanism;
@@ -391,7 +391,7 @@ public class SaslBindIT extends AbstractLdapTestUnit
     {
         LdapNetworkConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME,
             getLdapServer().getPortSSL(), true );
-        connection.getConfig().setTrustManagers( new NoVerificationTrustManager() );
+        connection.getConfig().setTrustManagers( new org.apache.directory.server.NoVerificationTrustManager() );
 
         SaslDigestMd5Request request = new SaslDigestMd5Request();
         request.setUsername( userDn.getRdn().getValue() );
diff --git a/server-integ/src/test/java/org/apache/directory/server/ssl/KeyStoreIT.java b/server-integ/src/test/java/org/apache/directory/server/ssl/KeyStoreIT.java
index aeb5ac936c..acf2cd79d9 100644
--- a/server-integ/src/test/java/org/apache/directory/server/ssl/KeyStoreIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/ssl/KeyStoreIT.java
@@ -42,7 +42,7 @@ import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 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.server.NoVerificationTrustManager;
 import org.apache.directory.server.annotations.CreateLdapServer;
 import org.apache.directory.server.annotations.CreateTransport;
 import org.apache.directory.server.core.annotations.CreateDS;
diff --git a/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java b/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java
index 06e9e97977..f4461e5f88 100644
--- a/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java
+++ b/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java
@@ -1066,7 +1066,11 @@ public final class ServiceBuilder
                 config.setSearchSizeLimit( replBean.getReplSearchSizeLimit() );
 
                 config.setUseTls( replBean.isReplUseTls() );
-                config.setStrictCertVerification( replBean.isReplStrictCertValidation() );
+
+                if ( !Strings.isEmpty( replBean.getReplTrustManagerFQCN() ) )
+                {
+                    config.setTrustManager( SyncReplConfiguration.createTrustManager( replBean.getReplTrustManagerFQCN() ) );
+                }
 
                 config.setConfigEntryDn( replBean.getDn() );