mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Nemanja Lukic
03.18.2011 6c119aa77f97501357fa8e7bb5fbf556b1f9f53d
Patch for OPENDJ-295
6 files modified
305 ■■■■■ changed files
opends/resource/config/config.ldif 1 ●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 13 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/DictionaryPasswordValidatorConfiguration.xml 49 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/extension.properties 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/DictionaryPasswordValidator.java 60 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java 180 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1666,6 +1666,7 @@
ds-cfg-dictionary-file: config/wordlist.txt
ds-cfg-case-sensitive-validation: false
ds-cfg-test-reversed-password: true
ds-cfg-check-substrings: false
dn: cn=Length-Based Password Validator,cn=Password Validators,cn=config
objectClass: top
opends/resource/schema/02-config.ldif
@@ -23,6 +23,7 @@
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions Copyright 2010-2011 ForgeRock AS.
#      Portions Copyright 2011 profiq, s.r.o.
#
#
# This file contains the attribute type and objectclass definitions for use
@@ -2712,6 +2713,14 @@
  NAME 'ds-cfg-log-control-oids'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.52
  NAME 'ds-cfg-check-substrings'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.53
  NAME 'ds-cfg-min-substring-length'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler'
  SUP top
@@ -3666,7 +3675,9 @@
  STRUCTURAL
  MUST ( ds-cfg-dictionary-file $
         ds-cfg-case-sensitive-validation $
         ds-cfg-test-reversed-password )
         ds-cfg-test-reversed-password $
         ds-cfg-check-substrings )
  MAY ds-cfg-min-substring-length
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.95
  NAME 'ds-cfg-attribute-value-password-validator'
opends/src/admin/defn/org/opends/server/admin/std/DictionaryPasswordValidatorConfiguration.xml
@@ -24,6 +24,7 @@
  !
  !
  !      Copyright 2007-2008 Sun Microsystems, Inc.
  |      Portions Copyright 2011 profiq, s.r.o.
  ! -->
<adm:managed-object name="dictionary-password-validator"
  plural-name="dictionary-password-validators"
@@ -145,4 +146,52 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="check-substrings" mandatory="true">
    <adm:synopsis>
      Indicates wheather this password validator is to match portions of
      the password string against dictionary words.
    </adm:synopsis>
    <adm:description>
      If "false" then only match the entire password against words
      otherwise ("true") check whether the password contains words.
    </adm:description>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>false</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-check-substrings</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="min-substring-length" mandatory="false">
    <adm:synopsis>
      Indicates the minimal length of the substring within the password
      in case substring checking is enabled.
    </adm:synopsis>
    <adm:description>
      If "check-substrings" option is set to true, then this parameter
      defines the length of the smallest word which should be used for
      substring matching. Use with caution because values below 3 might
      disqualify valid passwords.
    </adm:description>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>5</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:integer />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-min-substring-length</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/messages/messages/extension.properties
@@ -1123,7 +1123,7 @@
MILD_ERR_VATTR_NOT_SEARCHABLE_459=The %s attribute is not \
 searchable and should not be included in otherwise unindexed search filters
MILD_ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY_460=The provided \
 password was found in the server's dictionary
 password contained a word from the server's dictionary
MILD_ERR_DICTIONARY_VALIDATOR_NO_SUCH_FILE_461=The specified dictionary file \
 %s does not exist
MILD_ERR_DICTIONARY_VALIDATOR_CANNOT_READ_FILE_462=An error occurred while \
opends/src/server/org/opends/server/extensions/DictionaryPasswordValidator.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 profiq, s.r.o.
 */
package org.opends.server.extensions;
import org.opends.messages.Message;
@@ -124,9 +125,7 @@
  {
    // Get a handle to the current configuration.
    DictionaryPasswordValidatorCfg config = currentConfig;
    HashSet<String> dictionary = this.dictionary;
    // Check to see if the provided password is in the dictionary in the order
    // that it was provided.
    String password = newPassword.toString();
@@ -135,26 +134,43 @@
      password = toLowerCase(password);
    }
    if (dictionary.contains(password))
    // Check to see if we should verify the whole password or the substrings.
    // Either way, we initialise the minSubstringLength to the length of
    // the password which is the default behaviour ('check-substrings: false')
    int minSubstringLength = password.length();
    if (config.isCheckSubstrings())
    {
      // We apply the minimal substring length only if the provided value
      // is smaller then the actual password length
      if (config.getMinSubstringLength() < password.length())
      {
        minSubstringLength = config.getMinSubstringLength();
      }
    }
    // Verify if the dictionary contains the word(s) in the password
    if (isDictionaryBased(password, minSubstringLength))
    {
      invalidReason.append(
              ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY.get());
        ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY.get());
      return false;
    }
    // If we should try the reversed value, then do that as well.
    // If the reverse password checking is enabled, then verify if the
    // reverse value of the password is in the dictionary.
    if (config.isTestReversedPassword())
    {
      if (dictionary.contains(new StringBuilder(password).reverse().toString()))
      if (isDictionaryBased(
        new StringBuilder(password).reverse().toString(), minSubstringLength))
      {
        invalidReason.append(
                ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY.get());
          ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY.get());
        return false;
      }
    }
    // If we've gotten here, then the password is acceptable.
    return true;
  }
@@ -306,5 +322,25 @@
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
}
  private boolean isDictionaryBased(String password,
                                    int minSubstringLength)
  {
    HashSet<String> dictionary = this.dictionary;
    final int passwordLength = password.length();
    for (int i = 0; i < passwordLength; i++)
    {
      for (int j = i + minSubstringLength; j <= passwordLength; j++)
      {
        String substring = password.substring(i, j);
        if (dictionary.contains(substring))
        {
          return true;
        }
      }
    }
    return false;
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 profiq, s.r.o.
 */
package org.opends.server.extensions;
@@ -127,6 +128,8 @@
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: true",
         "ds-cfg-min-substring-length: 3",
         "",
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
         "objectClass: top",
@@ -139,6 +142,7 @@
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: true",
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: false",
         "",
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
         "objectClass: top",
@@ -150,7 +154,8 @@
         "ds-cfg-enabled: true",
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: true");
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: true");
    Object[][] array = new Object[entries.size()][1];
    for (int i=0; i < array.length; i++)
@@ -208,6 +213,7 @@
         "ds-cfg-dictionary-file: invalid",
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: false",
         "",
         // Dictionary file not a file.
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
@@ -221,6 +227,7 @@
         "ds-cfg-dictionary-file: config",
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: false",
         "",
         // Invalid case-sensitive-validation
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
@@ -234,6 +241,7 @@
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: invalid",
         "ds-cfg-test-reversed-password: true",
         "ds-cfg-check-substrings: false",
         "",
         // Invalid test-reversed-password
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
@@ -246,7 +254,37 @@
         "ds-cfg-enabled: true",
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: invalid");
         "ds-cfg-test-reversed-password: invalid",
         "ds-cfg-check-substrings: false",
         "",
         // Invalid check-substrings
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
         "objectClass: top",
         "objectClass: ds-cfg-password-validator",
         "objectClass: ds-cfg-dictionary-password-validator",
         "cn: Dictionary",
         "ds-cfg-java-class: org.opends.server.extensions." +
              "DictionaryPasswordValidator",
         "ds-cfg-enabled: true",
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: invalid",
         "ds-cfg-check-substrings: invalid",
         "",
         // Invalid min-substring-length
         "dn: cn=Dictionary,cn=Password Validators,cn=config",
         "objectClass: top",
         "objectClass: ds-cfg-password-validator",
         "objectClass: ds-cfg-dictionary-password-validator",
         "cn: Dictionary",
         "ds-cfg-java-class: org.opends.server.extensions." +
              "DictionaryPasswordValidator",
         "ds-cfg-enabled: true",
         "ds-cfg-dictionary-file: " + dictionaryFile,
         "ds-cfg-case-sensitive-validation: false",
         "ds-cfg-test-reversed-password: invalid",
         "ds-cfg-check-substrings: true",
         "ds-cfg-min-substring-length: invalid");
    Object[][] array = new Object[entries.size()][1];
    for (int i=0; i < array.length; i++)
@@ -311,6 +349,7 @@
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: false",
             "ds-cfg-test-reversed-password: true"),
        "notindictionary",
        true
@@ -330,6 +369,7 @@
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: false",
             "ds-cfg-test-reversed-password: true"),
        "password",
        false
@@ -350,6 +390,7 @@
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: false",
             "ds-cfg-test-reversed-password: true"),
        "PaSsWoRd",
        false
@@ -370,6 +411,7 @@
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: true",
             "ds-cfg-check-substrings: false",
             "ds-cfg-test-reversed-password: true"),
        "PaSsWoRd",
        true
@@ -454,6 +496,140 @@
        "dRoWsSaP",
        true
      },
      // Substrings checking configuration with a word in the dictionary,
      // case-sensitive matching enabled
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: true",
             "ds-cfg-check-substrings: true",
             "ds-cfg-min-substring-length: 3",
             "ds-cfg-test-reversed-password: true"),
        "oldpassword",
        false
      },
      // Substrings checking configuration with a word in the dictionary,
      // case-sensitive matching disabled
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: true",
             "ds-cfg-min-substring-length: 3",
             "ds-cfg-test-reversed-password: true"),
        "NewPassword",
        false
      },
      // Substrings checking configuration with a word in the dictionary,
      // case-sensitive matching enabled (dictionary word is lower case)
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: true",
             "ds-cfg-check-substrings: true",
             "ds-cfg-min-substring-length: 3",
             "ds-cfg-test-reversed-password: true"),
        "NewPassword",
        true
      },
      // Substrings checking configuration with a word in the dictionary,
      // case-sensitive matching disabled, and minimal substring length
      // of 5 while the password is only 3 characters
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: true",
             "ds-cfg-min-substring-length: 5",
             "ds-cfg-test-reversed-password: true"),
        "god",
        false
      },
      // Substrings checking configuration with a word in the dictionary,
      // case-sensitive matching disabled, and minimal substring length
      // of 5 while the word in the dictionary is only 3 characters
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-check-substrings: true",
             "ds-cfg-min-substring-length: 5",
             "ds-cfg-test-reversed-password: true"),
        "godblessus",
        true
      },
      // Substring checking configuration with a reverse of a word in the
      // dictionary, reversed matching enabled and case-insensitive
      // matching enabled
      new Object[]
      {
        TestCaseUtils.makeEntry(
             "dn: cn=Dictionary,cn=Password Validators,cn=config",
             "objectClass: top",
             "objectClass: ds-cfg-password-validator",
             "objectClass: ds-cfg-dictionary-password-validator",
             "cn: Dictionary",
             "ds-cfg-java-class: org.opends.server.extensions." +
                  "DictionaryPasswordValidator",
             "ds-cfg-enabled: true",
             "ds-cfg-dictionary-file: " + dictionaryFile,
             "ds-cfg-case-sensitive-validation: false",
             "ds-cfg-test-reversed-password: true",
             "ds-cfg-check-substrings: true"),
        "sdfdRoWsSaPqwerty",
        false
      },
    };
  }