From 080289c5388619b8b5059631c96a4d3b5922b6c1 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 07 Nov 2014 16:47:09 +0000
Subject: [PATCH] OPENDJ-1591 CR-5092 Re-implement UserPasswordEqualityMatchingRule to be compatible with SDK matching rules and schema
---
opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRule.java | 220 +++++++++++++++++-------------------
opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleFactory.java | 25 +--
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java | 2
opendj3-server-dev/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleFactory.java | 1
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java | 85 +++++++------
5 files changed, 163 insertions(+), 170 deletions(-)
diff --git a/opendj3-server-dev/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleFactory.java b/opendj3-server-dev/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleFactory.java
index 97d938e..eafa835 100644
--- a/opendj3-server-dev/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleFactory.java
+++ b/opendj3-server-dev/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleFactory.java
@@ -44,7 +44,6 @@
public final class AuthPasswordEqualityMatchingRuleFactory
extends MatchingRuleFactory<MatchingRuleCfg>
{
- //Associated Matching Rule.
private org.forgerock.opendj.ldap.schema.MatchingRule matchingRule;
/**
diff --git a/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRule.java b/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRule.java
index 2af5146..de7e7c2 100644
--- a/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRule.java
+++ b/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRule.java
@@ -26,102 +26,46 @@
*/
package org.opends.server.schema;
-
-
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DecodeException;
-import org.opends.server.api.EqualityMatchingRule;
+import org.forgerock.opendj.ldap.schema.MatchingRuleImpl;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
+import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.core.DirectoryServer;
-import static org.opends.server.schema.SchemaConstants.*;
-
-
+import static org.forgerock.opendj.ldap.Assertion.*;
+import static org.opends.server.core.DirectoryServer.*;
/**
- * This class implements the userPasswordMatch matching rule, which can be used
+ * Implementation of the userPasswordMatch matching rule, which can be used
* to determine whether a clear-text value matches an encoded password.
+ * <p>
+ * This matching rule serves a similar purpose to the equivalent
+ * AuthPasswordEqualityMatchingRule defined in RFC 3112 (http://tools.ietf.org/html/rfc3112).
*/
-class UserPasswordEqualityMatchingRule
- extends EqualityMatchingRule
+class UserPasswordEqualityMatchingRule implements MatchingRuleImpl
{
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
-
- /**
- * Creates a new instance of this userPasswordMatch matching rule.
- */
- public UserPasswordEqualityMatchingRule()
- {
- super();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Collection<String> getNames()
- {
- return Collections.singleton(EMR_USER_PASSWORD_NAME);
- }
-
-
- /**
- * Retrieves the OID for this matching rule.
- *
- * @return The OID for this matching rule.
- */
- @Override
- public String getOID()
- {
- return EMR_USER_PASSWORD_OID;
- }
-
-
-
- /**
- * Retrieves the description for this matching rule.
- *
- * @return The description for this matching rule, or <CODE>null</CODE> if
- * there is none.
- */
- @Override
- public String getDescription()
- {
- // There is no standard description for this matching rule.
- return EMR_USER_PASSWORD_DESCRIPTION;
- }
-
-
-
- /**
- * Retrieves the OID of the syntax with which this matching rule is
- * associated.
- *
- * @return The OID of the syntax with which this matching rule is associated.
- */
- @Override
- public String getSyntaxOID()
- {
- return SYNTAX_USER_PASSWORD_OID;
- }
-
-
+ private static final String EQUALITY_ID = "equality";
/**
* Retrieves the normalized form of the provided value, which is best suited
* for efficiently performing matching operations on that value.
*
- * @param value The value to be normalized.
+ * @param schema The schema.
+ * @param value The value to be normalized.
*
* @return The normalized version of the provided value.
*
@@ -129,13 +73,93 @@
* the associated attribute syntax.
*/
@Override
- public ByteString normalizeAttributeValue(ByteSequence value)
+ public ByteString normalizeAttributeValue(Schema schema, ByteSequence value)
throws DecodeException
{
// We will not alter the value in any way
return value.toByteString();
}
+ private final Collection<? extends Indexer> indexers = Collections.singleton(new Indexer()
+ {
+ @Override
+ public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
+ throws DecodeException
+ {
+ keys.add(normalizeAttributeValue(schema, value));
+ }
+
+ @Override
+ public String getIndexID()
+ {
+ return EQUALITY_ID;
+ }
+ });
+
+ /** {@inheritDoc} */
+ @Override
+ public Comparator<ByteSequence> comparator(Schema schema)
+ {
+ return ByteSequence.COMPARATOR;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue) throws DecodeException
+ {
+ return new Assertion()
+ {
+ final ByteString normalizedAssertionValue = normalizeAttributeValue(schema, assertionValue);
+
+ @Override
+ public ConditionResult matches(final ByteSequence normalizedAttributeValue)
+ {
+ return valuesMatch(normalizedAttributeValue, normalizedAssertionValue);
+ }
+
+ @Override
+ public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException
+ {
+ return factory.createExactMatchQuery(EQUALITY_ID, normalizedAssertionValue);
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Assertion getSubstringAssertion(Schema schema, ByteSequence subInitial,
+ List<? extends ByteSequence> subAnyElements, ByteSequence subFinal) throws DecodeException
+ {
+ return UNDEFINED_ASSERTION;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Assertion getGreaterOrEqualAssertion(Schema schema, ByteSequence value) throws DecodeException
+ {
+ return UNDEFINED_ASSERTION;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Assertion getLessOrEqualAssertion(Schema schema, ByteSequence value) throws DecodeException
+ {
+ return UNDEFINED_ASSERTION;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isIndexingSupported()
+ {
+ return indexers.isEmpty();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Collection<? extends Indexer> getIndexers()
+ {
+ return indexers;
+ }
/**
* Indicates whether the provided attribute value should be considered a match
@@ -152,30 +176,24 @@
* match for the provided assertion value, or <CODE>false</CODE> if
* not.
*/
- @Override
- public ConditionResult valuesMatch(ByteSequence attributeValue,
- ByteSequence assertionValue)
+ private ConditionResult valuesMatch(ByteSequence attributeValue, ByteSequence assertionValue)
{
// We must be able to decode the attribute value using the user password
// syntax.
String[] userPWComponents;
try
{
- userPWComponents =
- UserPasswordSyntax.decodeUserPassword(attributeValue.toString());
+ userPWComponents = UserPasswordSyntax.decodeUserPassword(attributeValue.toString());
}
catch (Exception e)
{
logger.traceException(e);
-
return ConditionResult.FALSE;
}
-
- // The first element of the array will be the scheme. Make sure that we
- // support the requested scheme.
- PasswordStorageScheme storageScheme =
- DirectoryServer.getPasswordStorageScheme(userPWComponents[0]);
+ // The first element of the array will be the scheme.
+ // Make sure that we support the requested scheme.
+ PasswordStorageScheme<?> storageScheme = getPasswordStorageScheme(userPWComponents[0]);
if (storageScheme == null)
{
// It's not a scheme that we can support.
@@ -183,34 +201,8 @@
}
// We support the scheme, so make the determination.
- return ConditionResult.valueOf(storageScheme.passwordMatches(
- assertionValue, ByteString.valueOf(userPWComponents[1])));
- }
-
-
-
- /**
- * Generates a hash code for the provided attribute value. This version of
- * the method will simply create a hash code from the normalized form of the
- * attribute value. For matching rules explicitly designed to work in cases
- * where byte-for-byte comparisons of normalized values is not sufficient for
- * determining equality (e.g., if the associated attribute syntax is based on
- * hashed or encrypted values), then this method must be overridden to provide
- * an appropriate implementation for that case.
- *
- * @param attributeValue The attribute value for which to generate the hash
- * code.
- *
- * @return The hash code generated for the provided attribute value.
- */
- @Override
- public int generateHashCode(ByteSequence attributeValue)
- {
- // Because of the variable encoding that may be used, we have no way of
- // comparing two user password values by hash code and therefore we'll
- // always return the same value so that the valuesMatch method will be
- // invoked to make the determination.
- return 1;
+ return ConditionResult.valueOf(
+ storageScheme.passwordMatches(assertionValue, ByteString.valueOf(userPWComponents[1])));
}
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleFactory.java b/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleFactory.java
index a276346..300f032 100644
--- a/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleFactory.java
+++ b/opendj3-server-dev/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleFactory.java
@@ -24,8 +24,6 @@
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2014 ForgeRock AS
*/
-
-
package org.opends.server.schema;
import java.util.Collection;
@@ -36,20 +34,18 @@
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.SchemaBuilder;
import org.opends.server.types.InitializationException;
+import static org.opends.server.schema.SchemaConstants.*;
+
/**
* This class is a factory class for UserPasswordExactEqualityMatchingRule.
*/
-public final class UserPasswordEqualityMatchingRuleFactory
- extends MatchingRuleFactory<MatchingRuleCfg>
+public final class UserPasswordEqualityMatchingRuleFactory extends MatchingRuleFactory<MatchingRuleCfg>
{
- //Associated Matching Rule.
private MatchingRule matchingRule;
-
-
-
/**
* {@inheritDoc}
*/
@@ -57,14 +53,15 @@
public final void initializeMatchingRule(MatchingRuleCfg configuration)
throws ConfigException, InitializationException
{
- // TODO: either delete completely UserPasswordEqualityMatchingRule or re-implement it
- // using SDK classes
- // Meanwhile, just returning UserPasswordExactEqualityMatchingRule instead
- matchingRule = CoreSchema.getInstance().getMatchingRule("1.3.6.1.4.1.26027.1.4.2");
+ matchingRule = new SchemaBuilder(CoreSchema.getInstance())
+ .buildMatchingRule(EMR_USER_PASSWORD_OID)
+ .names(EMR_USER_PASSWORD_NAME)
+ .syntaxOID(SYNTAX_USER_PASSWORD_OID).description(EMR_USER_PASSWORD_DESCRIPTION)
+ .implementation(new UserPasswordEqualityMatchingRule())
+ .addToSchema()
+ .toSchema().getMatchingRule(EMR_USER_PASSWORD_OID);
}
-
-
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
index cdd1269..acc491c 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/AuthPasswordEqualityMatchingRuleTest.java
@@ -137,7 +137,7 @@
}
- protected MatchingRule getRule()
+ private MatchingRule getRule()
{
AuthPasswordEqualityMatchingRuleFactory factory = new AuthPasswordEqualityMatchingRuleFactory();
try
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
index 8581471..13fec0d 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/UserPasswordEqualityMatchingRuleTest.java
@@ -32,26 +32,22 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.core.DirectoryServer;
import org.opends.server.extensions.SaltedMD5PasswordStorageScheme;
+import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.opends.server.types.DN;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import static org.testng.Assert.*;
-/**
- * Test the AuthPasswordEqualityMatchingRule.
- */
-public class UserPasswordEqualityMatchingRuleTest extends
- EqualityMatchingRuleTest
+
+@SuppressWarnings("javadoc")
+public class UserPasswordEqualityMatchingRuleTest extends SchemaTestCase
{
-
- /**
- * {@inheritDoc}
- */
- @Override
@DataProvider(name="equalitymatchingrules")
public Object[][] createEqualityMatchingRuleTest()
{
@@ -60,10 +56,6 @@
};
}
- /**
- * {@inheritDoc}
- */
- @Override
@DataProvider(name="equalityMatchingRuleInvalidValues")
public Object[][] createEqualityMatchingRuleInvalidValues()
{
@@ -75,41 +67,32 @@
ByteString bytePassword = ByteString.valueOf(password);
SaltedMD5PasswordStorageScheme scheme = new SaltedMD5PasswordStorageScheme();
- ConfigEntry configEntry =
- DirectoryServer.getConfigEntry(
+ ConfigEntry configEntry = DirectoryServer.getConfigEntry(
DN.valueOf("cn=Salted MD5,cn=Password Storage Schemes,cn=config"));
SaltedMD5PasswordStorageSchemeCfg configuration =
AdminTestCaseUtils.getConfiguration(
SaltedMD5PasswordStorageSchemeCfgDefn.getInstance(),
- configEntry.getEntry()
- );
+ configEntry.getEntry());
scheme.initializePasswordStorageScheme(configuration);
ByteString encodedAuthPassword =
scheme.encodePasswordWithScheme(bytePassword);
- return new Object[] {
- encodedAuthPassword.toString(), password, true};
+ return new Object[] { encodedAuthPassword.toString(), password, true };
}
- /**
- * {@inheritDoc}
- */
- @Override
@DataProvider(name="valuesMatch")
public Object[][] createValuesMatch()
{
try
{
return new Object[][] {
- // TODO : re-enable when matching rule is re-implemented
- // with SDK
-// generateValues("password"),
-// {"password", "something else", false},
-// {"password", "{wong}password", false},
-// {"password", "{SMD5}wrong", false}
+ generateValues("password"),
+ {"password", "something else", false},
+ {"password", "{wong}password", false},
+ {"password", "{SMD5}wrong", false}
};
}
catch (Exception e)
@@ -118,16 +101,38 @@
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- protected MatchingRule getRule()
+ @Test(dataProvider= "equalityMatchingRuleInvalidValues", expectedExceptions = { DecodeException.class })
+ public void equalityMatchingRulesInvalidValues(String value) throws Exception
{
- // TODO: temporary change to make test pass before
- // re-implementing matching rule with SDK classes.
- // new UserPasswordEqualityMatchingRule();
- return CoreSchema.getInstance().getMatchingRule(SchemaConstants.EMR_USER_PASSWORD_EXACT_OID);
+ getRule().normalizeAttributeValue(ByteString.valueOf(value));
+ }
+
+ /**
+ * Test the valuesMatch method used for extensible filters.
+ */
+ @Test(dataProvider= "valuesMatch")
+ public void testValuesMatch(String value1, String value2, Boolean result) throws Exception
+ {
+ MatchingRule rule = getRule();
+
+ ByteString normalizedValue1 = rule.normalizeAttributeValue(ByteString.valueOf(value1));
+ Assertion assertion = rule.getAssertion(ByteString.valueOf(value2));
+
+ ConditionResult liveResult = assertion.matches(normalizedValue1);
+ assertEquals(liveResult, ConditionResult.valueOf(result));
+ }
+
+ private MatchingRule getRule()
+ {
+ UserPasswordEqualityMatchingRuleFactory factory = new UserPasswordEqualityMatchingRuleFactory();
+ try
+ {
+ factory.initializeMatchingRule(null);
+ }
+ catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ return factory.getMatchingRules().iterator().next();
}
}
--
Gitblit v1.10.0