You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by lu...@apache.org on 2015/08/15 00:30:44 UTC

svn commit: r1695999 - in /directory/apacheds/trunk: core-integ/src/test/java/org/apache/directory/server/core/operations/add/ interceptors/hash/ interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ server-config/src/main/java/org/apa...

Author: lucastheisen
Date: Fri Aug 14 22:30:43 2015
New Revision: 1695999

URL: http://svn.apache.org/r1695999
Log:
DIRSERVER-2088 - Add the ability to specify additional fields that should be hashed by the hashing interceptors


Added:
    directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java   (with props)
    directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java   (with props)
    directory/apacheds/trunk/service-builder/src/test/
    directory/apacheds/trunk/service-builder/src/test/java/
    directory/apacheds/trunk/service-builder/src/test/java/org/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/
    directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java   (with props)
    directory/apacheds/trunk/service-builder/src/test/resources/
    directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties   (with props)
Modified:
    directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/PasswordHashingInterceptorTest.java
    directory/apacheds/trunk/interceptors/hash/pom.xml
    directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigurationElement.java
    directory/apacheds/trunk/server-config/src/main/resources/config.ldif
    directory/apacheds/trunk/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java

Modified: directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/PasswordHashingInterceptorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/PasswordHashingInterceptorTest.java?rev=1695999&r1=1695998&r2=1695999&view=diff
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/PasswordHashingInterceptorTest.java (original)
+++ directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/PasswordHashingInterceptorTest.java Fri Aug 14 22:30:43 2015
@@ -25,10 +25,12 @@ import static org.junit.Assert.assertFal
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+
 import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.Attribute;
@@ -42,8 +44,10 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.password.PasswordUtil;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.server.config.beans.HashInterceptorBean;
 import org.apache.directory.server.core.annotations.CreateDS;
 import org.apache.directory.server.core.api.interceptor.Interceptor;
+import org.apache.directory.server.core.hash.ConfigurableHashingInterceptor;
 import org.apache.directory.server.core.hash.CryptPasswordHashingInterceptor;
 import org.apache.directory.server.core.hash.Md5PasswordHashingInterceptor;
 import org.apache.directory.server.core.hash.Pkcs5s2PasswordHashingInterceptor;
@@ -89,6 +93,7 @@ public class PasswordHashingInterceptorT
         allMechanism.add( Ssha512PasswordHashingInterceptor.class );
         allMechanism.add( SshaPasswordHashingInterceptor.class );
         allMechanism.add( Pkcs5s2PasswordHashingInterceptor.class );
+        allMechanism.add( ConfigurableHashingInterceptor.class );
 
         Entry entry = new DefaultEntry( service.getSchemaManager(), "cn=test,ou=system",
             "objectClass: person",
@@ -102,7 +107,21 @@ public class PasswordHashingInterceptorT
 
         for ( int i = 0; i < allMechanism.size(); i++ )
         {
-            Interceptor hashMech = ( Interceptor ) allMechanism.get( i ).newInstance();
+            Class<?> clazz = allMechanism.get( i );
+            Interceptor hashMech = null;
+            if ( clazz == ConfigurableHashingInterceptor.class ) 
+            { 
+                HashInterceptorBean config = new HashInterceptorBean();
+                config.setHashAlgorithm( "SSHA-256" );
+                List<String> hashAttributes = new ArrayList<>();
+                hashAttributes.add( "userPassword" );
+                config.setHashAttributes( hashAttributes );
+                hashMech = new ConfigurableHashingInterceptor( config );
+            }
+            else 
+            {
+                hashMech = ( Interceptor ) clazz.newInstance();
+            }
             hashMech.init( service );
 
             // make sure to remove the last added mechanism

Modified: directory/apacheds/trunk/interceptors/hash/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/hash/pom.xml?rev=1695999&r1=1695998&r2=1695999&view=diff
==============================================================================
--- directory/apacheds/trunk/interceptors/hash/pom.xml (original)
+++ directory/apacheds/trunk/interceptors/hash/pom.xml Fri Aug 14 22:30:43 2015
@@ -75,6 +75,11 @@
     </dependency>
     
     <dependency>
+      <groupId>org.apache.directory.server</groupId>
+      <artifactId>apacheds-server-config</artifactId>
+    </dependency>
+    
+    <dependency>
       <groupId>org.apache.directory.api</groupId>
       <artifactId>api-ldap-client-api</artifactId>
     </dependency>

Added: directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java?rev=1695999&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java (added)
+++ directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java Fri Aug 14 22:30:43 2015
@@ -0,0 +1,187 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.server.core.hash;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.password.PasswordUtil;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.server.config.beans.HashInterceptorBean;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
+import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+
+
+/**
+ * An interceptor to hash a configurable set of attributeType(s) using
+ * a configurable hashing algorithm.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ConfigurableHashingInterceptor extends BaseInterceptor
+{
+
+    /** the hashing algorithm to be used */
+    private HashInterceptorBean config;
+    private LdapSecurityConstants algorithm;
+    private List<AttributeType> attributeTypes;
+
+
+    /**
+     * Creates a new instance of ConfigurableHashingInterceptor which hashes the
+     * incoming non-hashed attributeType(s) using the given algorithm.
+     * 
+     * @param config The configuration bean
+     */
+    public ConfigurableHashingInterceptor( HashInterceptorBean config )
+    {
+        this.config = config;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void add( AddOperationContext addContext ) throws LdapException
+    {
+        if ( algorithm == null )
+        {
+            next( addContext );
+            return;
+        }
+
+        for ( Attribute attribute : addContext.getEntry().getAttributes() ) 
+        {
+            if ( attributeTypes.contains( attribute.getAttributeType() ) ) 
+            {
+                includeHashed( attribute );    
+            }
+        }
+        
+        next( addContext );
+    }
+    
+    
+    public LdapSecurityConstants getAlgorithm() 
+    {
+        return algorithm;
+    }
+    
+    
+    public List<AttributeType> getAttributeTypes()
+    {
+        return Collections.unmodifiableList( attributeTypes );
+    }
+    
+    
+    private void includeHashed( Attribute attribute ) throws LdapInvalidAttributeValueException 
+    {
+        if ( attribute == null ) 
+        {
+            return;
+        }
+
+        // hash any values if necessary
+        List<byte[]> values = new ArrayList<>();
+        for ( Value<?> value : attribute ) 
+        {
+            byte[] bytes = value.getBytes();
+            if ( bytes == null )
+            {
+                // value may be empty, dont wanna attempt to hash empty
+                continue;
+            }
+
+            // check if the given field is already hashed
+            LdapSecurityConstants existingAlgo = PasswordUtil.findAlgorithm( bytes );
+            if ( existingAlgo == null ) 
+            {
+                // not already hashed, so hash it
+                values.add( PasswordUtil.createStoragePassword( bytes, algorithm ) );
+            }
+            else 
+            {
+                // already hashed, just pass through
+                values.add( bytes );
+            }
+        }
+        
+        // replace the value(s)
+        attribute.clear();
+        attribute.add( values.toArray( new byte[values.size()][] ) );
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void init( DirectoryService directoryService ) throws LdapException
+    {
+        // allow base initialization
+        super.init( directoryService );       
+
+        // initialize from config
+        algorithm = LdapSecurityConstants.getAlgorithm( config.getHashAlgorithm() );
+        attributeTypes = new ArrayList<>();
+        for ( String attributeType : config.getHashAttributes() ) 
+        {
+            attributeTypes.add( schemaManager.lookupAttributeTypeRegistry( attributeType ) );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void modify( ModifyOperationContext modifyContext ) throws LdapException
+    {
+        if ( algorithm == null )
+        {
+            next( modifyContext );
+            return;
+        }
+
+        List<Modification> mods = modifyContext.getModItems();
+
+        for ( Modification mod : mods ) 
+        {
+            Attribute attribute = mod.getAttribute();
+            if ( attributeTypes.contains( attribute.getAttributeType() ) )
+            {
+                includeHashed( attribute );
+            }
+        }
+
+        next( modifyContext );
+    }
+}

Propchange: directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ConfigurableHashingInterceptor.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigurationElement.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigurationElement.java?rev=1695999&r1=1695998&r2=1695999&view=diff
==============================================================================
--- directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigurationElement.java (original)
+++ directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/ConfigurationElement.java Fri Aug 14 22:30:43 2015
@@ -89,4 +89,10 @@ public @interface ConfigurationElement
      * @return the string value of the default value
      */
     String defaultValue() default "";
+    
+    /**
+     * Returns the list of string values that are the 
+     * default values when the element is multi-valued.
+     */
+    String[] defaultValues() default {};
 }

Added: directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java?rev=1695999&view=auto
==============================================================================
--- directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java (added)
+++ directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java Fri Aug 14 22:30:43 2015
@@ -0,0 +1,116 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.config.beans;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.server.config.ConfigurationElement;
+
+
+/**
+ * A bean used to store the hash interceptor configuration
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class HashInterceptorBean extends InterceptorBean
+{
+    /** The hash algorithm */
+    @ConfigurationElement(attributeType = "ads-hashAlgorithm", isOptional = true, defaultValue = "SSHA-256" )
+    private String hashAlgorithm;
+
+    /** The reference to the Password Policy component */
+    @ConfigurationElement(attributeType = "ads-hashAttribute", isOptional = true, defaultValues = {"userPassword"} )
+    private List<String> hashAttributes = new ArrayList<String>();
+
+
+    /**
+     * Creates a new AuthenticationInterceptorBean instance
+     */
+    public HashInterceptorBean()
+    {
+        super();
+    }
+
+
+    /**
+     * @return the hash algorithm
+     */
+    public String getHashAlgorithm()
+    {
+        return hashAlgorithm;
+    }
+
+
+    /**
+     * @return the attributes to hash
+     */
+    public List<String> getHashAttributes()
+    {
+        return hashAttributes;
+    }
+
+
+    /**
+     * @param hashAlgorithm The hash algorithm to use
+     */
+    public void setHashAlgorithm( String hashAlgorithm )
+    {
+        this.hashAlgorithm = hashAlgorithm;
+    }
+
+
+    /**
+     * @param hashAttributes The attributes that need to be hashed
+     */
+    public void setHashAttributes( List<String> hashAttributes )
+    {
+        this.hashAttributes = hashAttributes;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString( String tabs )
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( tabs ).append( "HashInterceptor :\n" );
+        sb.append( super.toString( tabs + "  " ) );
+
+        if ( hashAlgorithm != null ) {
+            sb.append( tabs ).append( "  hashAlgorithm : " )
+                    .append( hashAlgorithm ).append( "\n" );
+        }
+        if ( ( hashAttributes != null ) && ( hashAttributes.size() > 0 ) )
+        {
+            sb.append( tabs ).append( "  hashAttributes :\n" );
+
+            for ( String hashAttribute : hashAttributes )
+            {
+                sb.append( tabs ).append( "    " ).append( hashAttribute );
+            }
+        }
+
+        return sb.toString();
+    }
+}

Propchange: directory/apacheds/trunk/server-config/src/main/java/org/apache/directory/server/config/beans/HashInterceptorBean.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: directory/apacheds/trunk/server-config/src/main/resources/config.ldif
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-config/src/main/resources/config.ldif?rev=1695999&r1=1695998&r2=1695999&view=diff
==============================================================================
--- directory/apacheds/trunk/server-config/src/main/resources/config.ldif (original)
+++ directory/apacheds/trunk/server-config/src/main/resources/config.ldif Fri Aug 14 22:30:43 2015
@@ -195,6 +195,7 @@ dn: ads-interceptorId=passwordHashingInt
 objectclass: top
 objectclass: ads-base
 objectclass: ads-interceptor
+objectclass: ads-hashInterceptor
 ads-enabled: TRUE
 ads-interceptororder: 9
 ads-interceptorclassname: org.apache.directory.server.core.hash.SshaPasswordHashingInterceptor

Modified: directory/apacheds/trunk/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java?rev=1695999&r1=1695998&r2=1695999&view=diff
==============================================================================
--- directory/apacheds/trunk/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java (original)
+++ directory/apacheds/trunk/service-builder/src/main/java/org/apache/directory/server/config/builder/ServiceBuilder.java Fri Aug 14 22:30:43 2015
@@ -24,6 +24,7 @@ package org.apache.directory.server.conf
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -32,6 +33,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
+
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.ldif.LdapLdifException;
@@ -182,8 +184,16 @@ public class ServiceBuilder
             {
                 LOG.debug( "loading the interceptor class {} and instantiating",
                     interceptorBean.getInterceptorClassName() );
-                Interceptor interceptor = ( Interceptor ) Class.forName( interceptorBean.getInterceptorClassName() )
-                    .newInstance();
+                Class<?> clazz = Class.forName( interceptorBean.getInterceptorClassName() );
+                Interceptor interceptor = null;
+                try {
+                    Constructor<?> constructor = clazz.getDeclaredConstructor( interceptorBean.getClass() );
+                    interceptor = (Interceptor) constructor.newInstance( interceptorBean );
+                }
+                catch ( NoSuchMethodException e ) {
+                    interceptor = ( Interceptor ) Class.forName( interceptorBean.getInterceptorClassName() )
+                        .newInstance();
+                }
 
                 if ( interceptorBean instanceof AuthenticationInterceptorBean )
                 {

Added: directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java?rev=1695999&view=auto
==============================================================================
--- directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java (added)
+++ directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java Fri Aug 14 22:30:43 2015
@@ -0,0 +1,125 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.server.config.builder;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.loader.LdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.apache.directory.api.util.exception.Exceptions;
+import org.apache.directory.server.config.beans.HashInterceptorBean;
+import org.apache.directory.server.config.beans.InterceptorBean;
+import org.apache.directory.server.core.DefaultDirectoryService;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.interceptor.Interceptor;
+import org.apache.directory.server.core.hash.ConfigurableHashingInterceptor;
+import org.apache.directory.server.i18n.I18n;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests the factory methods of the ServiceBuilder.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ServiceBuilderTest 
+{
+    private static SchemaManager schemaManager;
+
+    @BeforeClass
+    public static void initSchemaManager() throws Exception
+    {
+        File partitionsDirectory = Files.createTempDirectory( "partitions" ).toFile();
+        File schemaPartitionDirectory = new File( partitionsDirectory, "schema" );
+        new DefaultSchemaLdifExtractor( partitionsDirectory ).extractOrCopy();
+
+        SchemaLoader loader = new LdifSchemaLoader( schemaPartitionDirectory );
+        schemaManager = new DefaultSchemaManager( loader );
+
+        // We have to load the schema now, otherwise we won't be able
+        // to initialize the Partitions, as we won't be able to parse
+        // and normalize their suffix Dn
+        schemaManager.loadAllEnabled();
+
+        List<Throwable> errors = schemaManager.getErrors();
+
+        if ( errors.size() != 0 )
+        {
+            fail( "unable to create initialize schema manager: " + I18n.err( I18n.ERR_317, Exceptions.printErrors( errors ) ) );
+        }
+    }
+
+    @Test
+    public void testCreateConfigurableHashInterceptor()
+    {
+        HashInterceptorBean bean = new HashInterceptorBean();
+        bean.setInterceptorClassName( "org.apache.directory.server.core.hash.ConfigurableHashingInterceptor" );
+        bean.setHashAlgorithm( "SSHA-256" );
+        List<String> hashAttributes = new ArrayList<>();
+        hashAttributes.add( "userPassword" );
+        hashAttributes.add( "cn" ); // why would i do this?... to test...
+        bean.setHashAttributes( hashAttributes );
+        
+        List<InterceptorBean> interceptorBeans = new ArrayList<>();
+        interceptorBeans.add( bean );
+
+        try 
+        {
+            List<Interceptor> interceptors = ServiceBuilder.createInterceptors( interceptorBeans );
+            assertNotNull( interceptors );
+            assertEquals( 1, interceptors.size() );
+            
+            Interceptor interceptor = interceptors.get( 0 );
+            assertEquals( ConfigurableHashingInterceptor.class, interceptor.getClass() );
+            
+            DirectoryService directoryService = new DefaultDirectoryService();
+            directoryService.setSchemaManager( schemaManager );
+            interceptor.init( directoryService );
+            
+            List<AttributeType> hashAttributeTypes = ((ConfigurableHashingInterceptor)interceptor).getAttributeTypes();
+            assertTrue( hashAttributeTypes.contains( schemaManager.getAttributeType( "userPassword" ) ) );
+            assertTrue( hashAttributeTypes.contains( schemaManager.getAttributeType( "cn" ) ) );
+            
+            assertEquals( LdapSecurityConstants.HASH_METHOD_SSHA256,
+                    ((ConfigurableHashingInterceptor)interceptor).getAlgorithm() );
+        }
+        catch ( Exception e ) 
+        {
+            fail( "unable to create hash interceptor: " + e.getMessage() );
+        }
+    }
+}

Propchange: directory/apacheds/trunk/service-builder/src/test/java/org/apache/directory/server/config/builder/ServiceBuilderTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties?rev=1695999&view=auto
==============================================================================
--- directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties (added)
+++ directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties Fri Aug 14 22:30:43 2015
@@ -0,0 +1,47 @@
+#############################################################################
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#############################################################################
+log4j.rootCategory=OFF, stdout, file
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c-%X{Replica}] - %m%n
+#log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c-%X{Replica}] %C{1}.%M@%L - %m%n
+
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
+log4j.appender.file.File=/tmp/server-integ.log
+log4j.appender.file.MaxFileSize=7168KB
+log4j.appender.file.MaxBackupIndex=100
+
+#log4j.logger.org=FATAL
+log4j.logger.jdbm.recman.BaseRecordManager=FATAL
+log4j.logger.org.apache.directory.server.OPERATION_LOG=FATAL
+log4j.logger.org.apache.directory.server.OPERATION_TIME=FATAL
+log4j.logger.org.apache.directory.api.CODEC_LOG=FATAL
+log4j.logger.org.apache.directory.server.ACI_LOG=FATAL
+log4j.logger.org.apache.directory.server.PROVIDER_LOG=FATAL
+log4j.logger.org.apache.directory.server.CONSUMER_LOG=FATAL
+log4j.logger.org.apache.directory.CURSOR_LOG=FATAL
+log4j.logger.org.apache.directory.api=FATAL
+log4j.logger.org.apache.directory.server=FATAL
+log4j.logger.net.sf.ehcache=FATAL
+log4j.logger.org.apache.mina=FATAL
+log4j.logger.org.apache.directory.mavibot=FATAL
+log4j.logger.org.apache.directory.api.ldap.model.schema=FATAL
+log4j.logger.org.apache.directory.mavibot=FATAL
+log4j.logger.org.apache.directory.server.replication=FATAL

Propchange: directory/apacheds/trunk/service-builder/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:executable = *