Add two new password validators to OpenDS:
- A validator which enforces a restriction that passwords must have at least a
specified number of unique characters (issue #1219).
- A validator which enforces a restriction that passwords may not have any
character which appears more than a specified number of times in a row (issue
#1220).
6 files added
3 files modified
| | |
| | | ds-cfg-minimum-password-length: 6 |
| | | ds-cfg-maximum-password-length: 0 |
| | | |
| | | dn: cn=Repeated Characters,cn=Password Validators,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-password-validator |
| | | objectClass: ds-cfg-repeated-characters-password-validator |
| | | cn: Repeated Characters |
| | | ds-cfg-password-validator-class: org.opends.server.extensions.RepeatedCharactersPasswordValidator |
| | | ds-cfg-password-validator-enabled: true |
| | | ds-cfg-maximum-consecutive-length: 2 |
| | | ds-cfg-case-sensitive-validation: false |
| | | |
| | | dn: cn=Similarity-Based Password Validator,cn=Password Validators,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-password-validator |
| | |
| | | ds-cfg-password-validator-enabled: true |
| | | ds-cfg-minimum-password-difference: 3 |
| | | |
| | | dn: cn=Unique Characters,cn=Password Validators,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-password-validator |
| | | objectClass: ds-cfg-unique-characters-password-validator |
| | | cn: Unique Characters |
| | | ds-cfg-password-validator-class: org.opends.server.extensions.UniqueCharactersPasswordValidator |
| | | ds-cfg-password-validator-enabled: true |
| | | ds-cfg-minimum-unique-characters: 5 |
| | | ds-cfg-case-sensitive-validation: false |
| | | |
| | | dn: cn=Plugins,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-branch |
| | |
| | | NAME 'ds-cfg-minimum-password-difference' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.322 |
| | | NAME 'ds-cfg-minimum-unique-characters' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.323 |
| | | NAME 'ds-cfg-maximum-consecutive-length' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.324 |
| | | NAME 'ds-cfg-case-sensitive-validation' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.1 |
| | | NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL |
| | | MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled ) |
| | |
| | | NAME 'ds-cfg-similarity-based-password-validator' |
| | | SUP ds-cfg-password-validator STRUCTURAL |
| | | MUST ds-cfg-minimum-password-difference X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.89 |
| | | NAME 'ds-cfg-unique-characters-password-validator' |
| | | SUP ds-cfg-password-validator STRUCTURAL |
| | | MUST ( ds-cfg-minimum-unique-characters $ ds-cfg-case-sensitive-validation ) |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.90 |
| | | NAME 'ds-cfg-repeated-characters-password-validator' |
| | | SUP ds-cfg-password-validator STRUCTURAL |
| | | MUST ( ds-cfg-maximum-consecutive-length $ ds-cfg-case-sensitive-validation ) |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="repeated-characters-password-validator" |
| | | plural-name="repeated-characters-password-validators" |
| | | package="org.opends.server.admin.std" extends="password-validator" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The |
| | | <adm:user-friendly-name /> |
| | | is used to determine whether a proposed password is acceptable based on |
| | | the number of times any character may appear consecutively in a password |
| | | value. |
| | | </adm:synopsis> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.90</ldap:oid> |
| | | <ldap:name>ds-cfg-repeated-characters-password-validator</ldap:name> |
| | | <ldap:superior>ds-cfg-password-validator</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="maximum-consecutive-length" mandatory="true"> |
| | | <adm:synopsis> |
| | | Specifies the maximum number of times that any character may appear |
| | | consecutively in a password value. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Specifies the maximum number of times that any character may appear |
| | | consecutively in a password value. A value of zero indicates that there |
| | | will be no maximum limit enforced. Changes to this configuration |
| | | attribute will take effect immediately. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.323</ldap:oid> |
| | | <ldap:name>ds-cfg-maximum-consecutive-length</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="case-sensitive-validation" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicates whether this password validator should treat password characters |
| | | in a case-sensitive manner. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Indicates whether this password validator should treat password characters |
| | | in a case-sensitive manner. A value of false indicates that any |
| | | differences in capitalization should be ignored when looking for |
| | | consecutive characters in the password. A value of true indicates that |
| | | a character should only be considered repeating if all consecutive |
| | | occurrences use the same capitalization. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.324</ldap:oid> |
| | | <ldap:name>ds-cfg-case-sensitive-validation</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| | | |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <adm:managed-object name="unique-characters-password-validator" |
| | | plural-name="unique-characters-password-validators" |
| | | package="org.opends.server.admin.std" extends="password-validator" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | The |
| | | <adm:user-friendly-name /> |
| | | is used to determine whether a proposed password is acceptable based on |
| | | the number of unique characters that it contains. |
| | | </adm:synopsis> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.89</ldap:oid> |
| | | <ldap:name>ds-cfg-unique-characters-password-validator</ldap:name> |
| | | <ldap:superior>ds-cfg-password-validator</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | <adm:property name="minimum-unique-characters" mandatory="true"> |
| | | <adm:synopsis> |
| | | Specifies the minimum number of unique characters that a password will be |
| | | allowed to contain. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Specifies the minimum number of unique characters that a password will be |
| | | allowed to contain. A value of zero indicates that there will be no |
| | | minimum value enforced. Changes to this configuration attribute will take |
| | | effect immediately. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:integer lower-limit="0" /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.322</ldap:oid> |
| | | <ldap:name>ds-cfg-minimum-unique-characters</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | <adm:property name="case-sensitive-validation" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicates whether this password validator should treat password characters |
| | | in a case-sensitive manner. |
| | | </adm:synopsis> |
| | | <adm:description> |
| | | Indicates whether this password validator should treat password characters |
| | | in a case-sensitive manner. A value of true indicates that a capital |
| | | letter should not be considered the same as its lowercase counterpart. |
| | | A value of false indicates that differences in capitalization should be |
| | | ignored when looking at the number of unique characters in the password. |
| | | </adm:description> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.324</ldap:oid> |
| | | <ldap:name>ds-cfg-case-sensitive-validation</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server. |
| | | RepeatedCharactersPasswordValidatorCfg; |
| | | import org.opends.server.api.PasswordValidator; |
| | | import org.opends.server.core.Operation; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides an OpenDS password validator that may be used to ensure |
| | | * that proposed passwords are not allowed to have the same character appear |
| | | * several times consecutively. |
| | | */ |
| | | public class RepeatedCharactersPasswordValidator |
| | | extends PasswordValidator<RepeatedCharactersPasswordValidatorCfg> |
| | | implements ConfigurationChangeListener< |
| | | RepeatedCharactersPasswordValidatorCfg> |
| | | { |
| | | // The current configuration for this password validator. |
| | | private RepeatedCharactersPasswordValidatorCfg currentConfig; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this repeated characters password validator. |
| | | */ |
| | | public RepeatedCharactersPasswordValidator() |
| | | { |
| | | super(); |
| | | |
| | | // No implementation is required here. All initialization should be |
| | | // performed in the initializePasswordValidator() method. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordValidator( |
| | | RepeatedCharactersPasswordValidatorCfg configuration) |
| | | { |
| | | configuration.addRepeatedCharactersChangeListener(this); |
| | | currentConfig = configuration; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void finalizePasswordValidator() |
| | | { |
| | | currentConfig.removeRepeatedCharactersChangeListener(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean passwordIsAcceptable(ByteString newPassword, |
| | | Set<ByteString> currentPasswords, |
| | | Operation operation, Entry userEntry, |
| | | StringBuilder invalidReason) |
| | | { |
| | | // Get a handle to the current configuration and see if we need to count |
| | | // the number of repeated characters in the password. |
| | | RepeatedCharactersPasswordValidatorCfg config = currentConfig; |
| | | int maxRepeats = config.getMaximumConsecutiveLength(); |
| | | if (maxRepeats <= 0) |
| | | { |
| | | // We don't need to check anything, so the password will be acceptable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | // Get the password as a string. If we should use case-insensitive |
| | | // validation, then convert it to use all lowercase characters. |
| | | String passwordString = newPassword.stringValue(); |
| | | if (! config.isCaseSensitiveValidation()) |
| | | { |
| | | passwordString = passwordString.toLowerCase(); |
| | | } |
| | | |
| | | |
| | | // Create variables to keep track of the last character we've seen and how |
| | | // many times we have seen it. |
| | | char lastCharacter = '\u0000'; |
| | | int consecutiveCount = 0; |
| | | |
| | | |
| | | // Iterate through the characters in the password. If the consecutive |
| | | // count ever gets too high, then fail. |
| | | for (int i=0; i < passwordString.length(); i++) |
| | | { |
| | | char currentCharacter = passwordString.charAt(i); |
| | | if (currentCharacter == lastCharacter) |
| | | { |
| | | consecutiveCount++; |
| | | if (consecutiveCount > maxRepeats) |
| | | { |
| | | int msgID = MSGID_REPEATEDCHARS_VALIDATOR_TOO_MANY_CONSECUTIVE; |
| | | String message = getMessage(msgID, maxRepeats); |
| | | invalidReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | lastCharacter = currentCharacter; |
| | | consecutiveCount = 1; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | RepeatedCharactersPasswordValidatorCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // All of the necessary validation should have been performed automatically, |
| | | // so if we get to this point then the new configuration will be acceptable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | RepeatedCharactersPasswordValidatorCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | // For this password validator, we will always be able to successfully apply |
| | | // the new configuration. |
| | | currentConfig = configuration; |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.UniqueCharactersPasswordValidatorCfg; |
| | | import org.opends.server.api.PasswordValidator; |
| | | import org.opends.server.core.Operation; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides an OpenDS password validator that may be used to ensure |
| | | * that proposed passwords contain at least a specified number of different |
| | | * characters. |
| | | */ |
| | | public class UniqueCharactersPasswordValidator |
| | | extends PasswordValidator<UniqueCharactersPasswordValidatorCfg> |
| | | implements ConfigurationChangeListener< |
| | | UniqueCharactersPasswordValidatorCfg> |
| | | { |
| | | // The current configuration for this password validator. |
| | | private UniqueCharactersPasswordValidatorCfg currentConfig; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this unique characters password validator. |
| | | */ |
| | | public UniqueCharactersPasswordValidator() |
| | | { |
| | | super(); |
| | | |
| | | // No implementation is required here. All initialization should be |
| | | // performed in the initializePasswordValidator() method. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordValidator( |
| | | UniqueCharactersPasswordValidatorCfg configuration) |
| | | { |
| | | configuration.addUniqueCharactersChangeListener(this); |
| | | currentConfig = configuration; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void finalizePasswordValidator() |
| | | { |
| | | currentConfig.removeUniqueCharactersChangeListener(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean passwordIsAcceptable(ByteString newPassword, |
| | | Set<ByteString> currentPasswords, |
| | | Operation operation, Entry userEntry, |
| | | StringBuilder invalidReason) |
| | | { |
| | | // Get a handle to the current configuration and see if we need to count |
| | | // the number of unique characters in the password. |
| | | UniqueCharactersPasswordValidatorCfg config = currentConfig; |
| | | int minUniqueCharacters = config.getMinimumUniqueCharacters(); |
| | | if (minUniqueCharacters <= 0) |
| | | { |
| | | // We don't need to check anything, so the password will be acceptable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | // Create a set that will be used to keep track of the unique characters |
| | | // contained in the proposed password. |
| | | HashSet<Character> passwordCharacters = new HashSet<Character>(); |
| | | |
| | | // Iterate through the characters in the new password and place them in the |
| | | // set as needed. If we should behave in a case-insensitive manner, then |
| | | // convert all the characters to lowercase first. |
| | | String passwordString = newPassword.stringValue(); |
| | | if (! config.isCaseSensitiveValidation()) |
| | | { |
| | | passwordString = passwordString.toLowerCase(); |
| | | } |
| | | |
| | | for (int i=0; i < passwordString.length(); i++) |
| | | { |
| | | passwordCharacters.add(passwordString.charAt(i)); |
| | | } |
| | | |
| | | // If the size of the password characters set is less than the minimum |
| | | // number of allowed unique characters, then we will reject the password. |
| | | if (passwordCharacters.size() < minUniqueCharacters) |
| | | { |
| | | int msgID = MSGID_UNIQUECHARS_VALIDATOR_NOT_ENOUGH_UNIQUE_CHARS; |
| | | String message = getMessage(msgID, minUniqueCharacters); |
| | | invalidReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | UniqueCharactersPasswordValidatorCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // All of the necessary validation should have been performed automatically, |
| | | // so if we get to this point then the new configuration will be acceptable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | UniqueCharactersPasswordValidatorCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | // For this password validator, we will always be able to successfully apply |
| | | // the new configuration. |
| | | currentConfig = configuration; |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the same character |
| | | * appears too many times in consecutive order in a given password. This |
| | | * takes a single argument, which is the maximum number of times a character |
| | | * may appear in consecutive order. |
| | | */ |
| | | public static final int MSGID_REPEATEDCHARS_VALIDATOR_TOO_MANY_CONSECUTIVE = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 457; |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if a given password does |
| | | * not have enough unique characters. This takes a single argument, which is |
| | | * the minimum number of unique characters that a password may contain. |
| | | */ |
| | | public static final int MSGID_UNIQUECHARS_VALIDATOR_NOT_ENOUGH_UNIQUE_CHARS = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 458; |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | registerMessage(MSGID_DYNAMICGROUP_CANNOT_RETURN_ENTRY, |
| | | "The server encountered a timeout while attempting to " + |
| | | "add user %s to the member list for dynamic group %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_REPEATEDCHARS_VALIDATOR_TOO_MANY_CONSECUTIVE, |
| | | "The provided password contained too many instances " + |
| | | "of the same character appearing consecutively. The " + |
| | | "maximum number of times the same character may appear " + |
| | | "consecutively in a password is %d."); |
| | | |
| | | |
| | | registerMessage(MSGID_UNIQUECHARS_VALIDATOR_NOT_ENOUGH_UNIQUE_CHARS, |
| | | "The provided password does not contain enough unique " + |
| | | "characters. The minimum number of unique characters " + |
| | | "that may appear in a user password is %d."); |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | RepeatedCharactersPasswordValidatorCfgDefn; |
| | | import org.opends.server.admin.std.server. |
| | | RepeatedCharactersPasswordValidatorCfg; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.ModificationType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the repeated characters password validator. |
| | | */ |
| | | public class RepeatedCharactersPasswordValidatorTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of valid configuration entries that may be used to |
| | | * initialize the validator. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "validConfigs") |
| | | public Object[][] getValidConfigs() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: true", |
| | | "", |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 0", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | Object[][] array = new Object[entries.size()][1]; |
| | | for (int i=0; i < array.length; i++) |
| | | { |
| | | array[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return array; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the process of initializing the server with valid configurations. |
| | | * |
| | | * @param entry The configuration entry to use for the initialization. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "validConfigs") |
| | | public void testInitializeWithValidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), e); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of invalid configuration entries. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "invalidConfigs") |
| | | public Object[][] getInvalidConfigs() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | // Missing maximum consecutive length |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | // Missing case-sensitive validation |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "", |
| | | // Non-numeric maximum consecutive length |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: non-numeric", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | // Non-boolean case-sensitive validation |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: non-boolean", |
| | | "", |
| | | // Maximum consecutive length out of range. |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: -1", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | Object[][] array = new Object[entries.size()][1]; |
| | | for (int i=0; i < array.length; i++) |
| | | { |
| | | array[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return array; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the process of initializing the server with invalid configurations. |
| | | * |
| | | * @param entry The configuration entry to use for the initialization. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "invalidConfigs", |
| | | expectedExceptions = { ConfigException.class, |
| | | InitializationException.class }) |
| | | public void testInitializeWithInvalidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), e); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * within the constraints of the password validator. Case-sensitivity will |
| | | * not be an issue. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptable2Consecutive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("password"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "password"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * outside of the constraints of the password validator. Case-sensitivity |
| | | * will not be an issue. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptable3Consecutive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("passsword"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "passsword"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * within the constraints of the password validator only because it is |
| | | * configured to operate in a case-sensitive manner. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableCaseSensitive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("passSword"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "passSword"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * outside of the constraints of the password validator because it is |
| | | * configured to operate in a case-insensitive manner. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableCaseInsensitive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("passSword"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "passSword"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method when the validator is |
| | | * configured to accept any number of repeated characters. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableUnlimitedRepeats() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 0", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("aaaaaaaa"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "aaaaaaaa"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the ability of the password validator to change its behavior when |
| | | * the configuration is updated. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableConfigurationChange() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 0", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | RepeatedCharactersPasswordValidator validator = |
| | | new RepeatedCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("aaaaaaaa"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "aaaaaaaa"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | Entry updatedValidatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Repeated Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-repeated-characters-password-validator", |
| | | "cn: Repeated Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "RepeatedCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-maximum-consecutive-length: 2", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | RepeatedCharactersPasswordValidatorCfg updatedConfiguration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | RepeatedCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | updatedValidatorEntry); |
| | | |
| | | ArrayList<String> unacceptableReasons = new ArrayList<String>(); |
| | | assertTrue(validator.isConfigurationChangeAcceptable(updatedConfiguration, |
| | | unacceptableReasons), |
| | | String.valueOf(unacceptableReasons)); |
| | | |
| | | ConfigChangeResult changeResult = |
| | | validator.applyConfigurationChange(updatedConfiguration); |
| | | assertEquals(changeResult.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | UniqueCharactersPasswordValidatorCfgDefn; |
| | | import org.opends.server.admin.std.server. |
| | | UniqueCharactersPasswordValidatorCfg; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.ModificationType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the unique characters password validator. |
| | | */ |
| | | public class UniqueCharactersPasswordValidatorTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of valid configuration entries that may be used to |
| | | * initialize the validator. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "validConfigs") |
| | | public Object[][] getValidConfigs() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: true", |
| | | "", |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 0", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | Object[][] array = new Object[entries.size()][1]; |
| | | for (int i=0; i < array.length; i++) |
| | | { |
| | | array[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return array; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the process of initializing the server with valid configurations. |
| | | * |
| | | * @param entry The configuration entry to use for the initialization. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "validConfigs") |
| | | public void testInitializeWithValidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), e); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of invalid configuration entries. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "invalidConfigs") |
| | | public Object[][] getInvalidConfigs() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | // Missing minimum unique characters |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | // Missing case-sensitive validation |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "", |
| | | // Non-numeric minimum unique characters |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: non-numeric", |
| | | "ds-cfg-case-sensitive-validation: false", |
| | | "", |
| | | // Non-boolean case-sensitive validation |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: non-boolean", |
| | | "", |
| | | // Minimum unique characters out of range. |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: -1", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | Object[][] array = new Object[entries.size()][1]; |
| | | for (int i=0; i < array.length; i++) |
| | | { |
| | | array[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return array; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the process of initializing the server with invalid configurations. |
| | | * |
| | | * @param entry The configuration entry to use for the initialization. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "invalidConfigs", |
| | | expectedExceptions = { ConfigException.class, |
| | | InitializationException.class }) |
| | | public void testInitializeWithInvalidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), e); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * within the constraints of the password validator. Case-sensitivity will |
| | | * not be an issue. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptable7Unique() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("password"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "password"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * outside the constraints of the password validator. Case-sensitivity will |
| | | * not be an issue. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptable4Unique() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("passw"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "passw"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * within the constraints of the password validator only because it uses |
| | | * case-sensitive validation. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableCaseSensitive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("pasSw"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "pasSw"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method with a password that falls |
| | | * outside the constraints of the password validator because it uses |
| | | * case-insensitive validation. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableCaseInsensitive() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: false"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("pasSw"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "pasSw"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code passwordIsAcceptable} method when the validator is |
| | | * configured to accept any number of unique characters. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableAnyNumberOfCharacters() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 0", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("aaaaaaaa"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "aaaaaaaa"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the ability of the password validator to change its behavior when |
| | | * the configuration is updated. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testPasswordIsAcceptableConfigurationChange() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: doesntmatter"); |
| | | |
| | | Entry validatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 0", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | validatorEntry); |
| | | |
| | | UniqueCharactersPasswordValidator validator = |
| | | new UniqueCharactersPasswordValidator(); |
| | | validator.initializePasswordValidator(configuration); |
| | | |
| | | ASN1OctetString password = new ASN1OctetString("aaaaaaaa"); |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("userpassword", "aaaaaaaa"))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), |
| | | DN.decode("uid=test.user,o=test"), mods); |
| | | |
| | | StringBuilder invalidReason = new StringBuilder(); |
| | | assertTrue(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason), |
| | | invalidReason.toString()); |
| | | |
| | | Entry updatedValidatorEntry = TestCaseUtils.makeEntry( |
| | | "dn: cn=Unique Characters,cn=Password Validators,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-password-validator", |
| | | "objectClass: ds-cfg-unique-characters-password-validator", |
| | | "cn: Unique Characters", |
| | | "ds-cfg-password-validator-class: org.opends.server.extensions." + |
| | | "UniqueCharactersPasswordValidator", |
| | | "ds-cfg-password-validator-enabled: true", |
| | | "ds-cfg-minimum-unique-characters: 5", |
| | | "ds-cfg-case-sensitive-validation: true"); |
| | | |
| | | UniqueCharactersPasswordValidatorCfg updatedConfiguration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | UniqueCharactersPasswordValidatorCfgDefn.getInstance(), |
| | | updatedValidatorEntry); |
| | | |
| | | ArrayList<String> unacceptableReasons = new ArrayList<String>(); |
| | | assertTrue(validator.isConfigurationChangeAcceptable(updatedConfiguration, |
| | | unacceptableReasons), |
| | | String.valueOf(unacceptableReasons)); |
| | | |
| | | ConfigChangeResult changeResult = |
| | | validator.applyConfigurationChange(updatedConfiguration); |
| | | assertEquals(changeResult.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | assertFalse(validator.passwordIsAcceptable(password, |
| | | new HashSet<ByteString>(0), modifyOperation, |
| | | userEntry, invalidReason)); |
| | | |
| | | validator.finalizePasswordValidator(); |
| | | } |
| | | } |
| | | |