Directory Services 7.2.5

Passwords

DS servers simplify safe, centralized password management. DS servers use password policies to govern passwords.

Which password policy applies

The operational attribute, pwdPolicySubentry, identifies an account’s password policy. The default global access control instructions prevent this operational attribute from being visible to normal users. The following example grants access to a group of administrators:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: ou=People,dc=example,dc=com
changetype: modify
add: aci
aci: (targetattr = "pwdPolicySubentry||ds-pwp-password-policy-dn")
 (version 3.0;acl "Allow Administrators to manage user's password policy";
 allow (all) (groupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com");)
EOF

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDN dc=example,dc=com \
 "(uid=bjensen)" \
 pwdPolicySubentry

dn: uid=bjensen,ou=People,dc=example,dc=com
pwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config

Configure password policies

Adjust the default password policy

You can reconfigure the default password policy, for example, to check that passwords do not contain complete attribute values, and to prevent password reuse. The default policy is a per-server password policy.

  1. Apply the changes to the default password policy:

    $ dsconfig \
     set-password-policy-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "Default Password Policy" \
     --set password-history-count:7 \
     --set password-validator:Attribute\ Value \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
  2. Check your work:

    $ dsconfig \
     get-password-policy-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "Default Password Policy" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Property                                  : Value(s)
    ------------------------------------------:--------------------------
    account-status-notification-handler       : -
    allow-expired-password-changes            : false
    allow-user-password-changes               : true
    default-password-storage-scheme           : PBKDF2-HMAC-SHA256
    deprecated-password-storage-scheme        : -
    expire-passwords-without-warning          : false
    force-change-on-add                       : false
    force-change-on-reset                     : false
    grace-login-count                         : 0
    idle-lockout-interval                     : 0 s
    last-login-time-attribute                 : -
    last-login-time-format                    : -
    lockout-duration                          : 0 s
    lockout-failure-count                     : 0
    lockout-failure-expiration-interval       : 0 s
    max-password-age                          : 0 s
    max-password-reset-age                    : 0 s
    min-password-age                          : 0 s
    password-attribute                        : userPassword
    password-change-requires-current-password : false
    password-expiration-warning-interval      : 5 d
    password-generator                        : Random Password Generator
    password-history-count                    : 7
    password-history-duration                 : 0 s
    password-validator                        : Attribute Value
    previous-last-login-time-format           : -
    require-change-by-time                    : -
    require-secure-authentication             : true
    require-secure-password-changes           : true
  3. Test changes to the default password policy.

    For example, the following tests demonstrate the attribute value password validator. The attribute value password validator rejects a new password when the password is contained in attribute values on the user’s entry.

    By default, the attribute value password validator checks all attributes, checks whether portions of the password string match attribute values, where the portions are strings of length 5, and checks the reverse of the password as well:

    $ dsconfig \
     get-password-validator-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --validator-name Attribute\ Value \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Property               : Value(s)
    -----------------------:--------------------------------------------------
    check-substrings       : true
    enabled                : true
    match-attribute        : All attributes in the user entry will be checked.
    min-substring-length   : 5
    test-reversed-password : true

    Consider the attributes present on Babs Jensen’s entry:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=bjensen,ou=People,dc=example,dc=com \
     --bindPassword hifalutin \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)"
    
    dn: uid=bjensen,ou=People,dc=example,dc=com
    objectClass: person
    objectClass: cos
    objectClass: oauth2TokenObject
    objectClass: inetOrgPerson
    objectClass: organizationalPerson
    objectClass: posixAccount
    objectClass: top
    classOfService: bronze
    cn: Barbara Jensen
    cn: Babs Jensen
    departmentNumber: 3001
    description: Original description
    diskQuota: 10 GB
    facsimileTelephoneNumber: +1 408 555 1992
    gidNumber: 1000
    givenName: Barbara
    homeDirectory: /home/bjensen
    l: San Francisco
    mail: bjensen@example.com
    mailQuota: 1 GB
    manager: uid=trigden, ou=People, dc=example,dc=com
    oauth2Token: {"access_token":"123","expires_in":59,"token_type":"Bearer","refresh_token":"456"}
    ou: Product Development
    ou: People
    preferredLanguage: en, ko;q=0.8
    roomNumber: 0209
    sn: Jensen
    street: 201 Mission Street Suite 2900
    telephoneNumber: +1 408 555 1862
    uid: bjensen
    uidNumber: 1076

    Using the attribute value password validator, passwords like bjensen12 and babsjensenspwd are not valid because substrings of the password match complete attribute values:

    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword hifalutin \
     --newPassword bjensen12
    
    The LDAP password modify operation failed: 19 (Constraint Violation)
    Additional Information:  The provided new password failed the validation
    checks defined in the server: The provided password was found in another
    attribute in the user entry
    
    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword hifalutin \
     --newPassword babsjensenspwd
    
    The LDAP password modify operation failed: 19 (Constraint Violation)
    Additional Information:  The provided new password failed the validation
    checks defined in the server: The provided password was found in another
    attribute in the user entry

    The attribute value password validator does not check, however, whether the password contains substrings of attribute values:

    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword hifalutin \
     --newPassword babsp4ssw0rd
    
    The LDAP password modify operation was successful
    
    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword babsp4ssw0rd \
     --newPassword example.com
    
    The LDAP password modify operation was successful

    To avoid the problem of the latter example, you could use a dictionary password validator where the dictionary includes example.com.

You can configure a password policy inspired by NIST 800-63 requirements:

  • Use a strong password storage scheme.

  • Enforce a minimum password length of 8 characters.

  • Check for matches in a dictionary of compromised passwords.

  • Do not use composition rules for password validation.

    In other words, do not require a mix of special characters, upper and lower case letters, numbers, or other composition rules.

  • Do not enforce arbitrary password changes.

    In other words, do not set a maximum password age.

Follow these steps to set up a replicated, NIST-inspired LDAP subentry password policy:

  1. Gzip a copy of a text file of common compromised passwords, one word per line.

    This example shows the gzipped text file as /tmp/10k_most_common.gz. After successfully updating a subentry password policy with the dictionary data, the input file is no longer required. Lists of common passwords can be found online.

  2. Make sure you have enabled a strong storage scheme.

    Creating a password storage scheme requires access to edit the server configuration, which you might not have when creating a subentry password policy. This example therefore uses the PBKDF2-HMAC-SHA512 storage scheme, which is enabled by default to use 10,000 iterations.

    This scheme is intentionally much slower and more CPU-intensive than the PBKDF2-HMAC-SHA256 scheme with 10 iterations used by the default password policy when you install DS. Test that you have enough resources to sustain the expected peak rates of impacted operations before using a much stronger password storage scheme in your production deployment.

    Impacted operations include:

    • Adding or importing entries with passwords.

    • Authenticating using a password, such as simple bind.

    • Updating or resetting a password.

  3. Make sure password policy administrators have the subentry-write privilege, and any required ACIs needed to write password policy subentries in the directory data.

    The following example grants access to password administrators. The administrator accounts are in the data where the password policy is to be stored:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: cn=subentry-write privilege for administrators,dc=example,dc=com
    objectClass: collectiveAttributeSubentry
    objectClass: extensibleObject
    objectClass: subentry
    objectClass: top
    cn: subentry-write privilege for administrators
    ds-privilege-name;collective: subentry-write
    subtreeSpecification: {base "ou=people", specificationFilter
      "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" }
    
    dn: dc=example,dc=com
    changetype: modify
    add: aci
    aci: (target="ldap:///dc=example,dc=com")
     (targetattr = "*||ds-pwp-password-policy-dn||pwdPolicySubentry||subtreeSpecification")
     (version 3.0; acl "Admins can manage entries and password policies"; allow(all)
     groupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
    EOF

    Notice here that the directory superuser, uid=admin, assigns privileges. Any administrator with the privilege-change privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the bypass-acl privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the privilege-change privilege to normal administrator users.

  4. Create the password policy as one of the password policy administrators:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: cn=NIST inspired policy,dc=example,dc=com
    objectClass: top
    objectClass: subentry
    objectClass: ds-pwp-password-policy
    objectClass: ds-pwp-validator
    objectClass: ds-pwp-length-based-validator
    objectClass: ds-pwp-dictionary-validator
    cn: NIST inspired policy
    ds-pwp-password-attribute: userPassword
    ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA512
    ds-pwp-length-based-min-password-length: 8
    ds-pwp-dictionary-data:<file:///tmp/10k_most_common.gz
    subtreeSpecification: {base "ou=people", specificationFilter "(objectclass=person)" }
    EOF

    After successfully adding the policy with the dictionary data, you can delete the input file.

  5. Check the password policy works appropriately.

    The following example shows a rejected password modification:

    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword hifalutin \
     --newPassword secret12
    
    The LDAP password modify operation failed: 19 (Constraint Violation)
    Additional Information:  The provided new password failed the validation
    checks defined in the server: The provided password was found in another
    attribute in the user entry

    The following example shows an accepted password modification:

    $ ldappasswordmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
     --bindPassword hifalutin \
     --newPassword aET1OjQeVJECSMgxDPs3U6In
    
    The LDAP password modify operation was successful

Create a per-server password policy

This example adds a per-server password policy for new users who have not yet used their credentials to bind:

  1. Create the new password policy:

    $ dsconfig \
     create-password-policy \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "New Account Password Policy" \
     --set default-password-storage-scheme:PBKDF2-HMAC-SHA256 \
     --set force-change-on-add:true \
     --set password-attribute:userPassword \
     --type password-policy \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

    As per-server password policies are not replicated, repeat this step on all replica directory servers.

  2. Check your work:

    $ dsconfig \
     get-password-policy-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "New Account Password Policy" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Property                                  : Value(s)
    ------------------------------------------:-------------------
    account-status-notification-handler       : -
    allow-expired-password-changes            : false
    allow-user-password-changes               : true
    default-password-storage-scheme           : PBKDF2-HMAC-SHA256
    deprecated-password-storage-scheme        : -
    expire-passwords-without-warning          : false
    force-change-on-add                       : true
    force-change-on-reset                     : false
    grace-login-count                         : 0
    idle-lockout-interval                     : 0 s
    last-login-time-attribute                 : -
    last-login-time-format                    : -
    lockout-duration                          : 0 s
    lockout-failure-count                     : 0
    lockout-failure-expiration-interval       : 0 s
    max-password-age                          : 0 s
    max-password-reset-age                    : 0 s
    min-password-age                          : 0 s
    password-attribute                        : userPassword
    password-change-requires-current-password : false
    password-expiration-warning-interval      : 5 d
    password-generator                        : -
    password-history-count                    : 0
    password-history-duration                 : 0 s
    password-validator                        : -
    previous-last-login-time-format           : -
    require-change-by-time                    : -
    require-secure-authentication             : false
    require-secure-password-changes           : false
  3. Change the user’s password policy after the password is successfully updated.

    For instructions on assigning a per-server password policy, see Assign a password policy to a user.

Test password policies

Use the LDAP password quality advice control to test passwords, and to validate that a password policy produces the expected failures when a new password does not comply with its requirements.

The feature is available over LDAP, and also over REST for HTTP applications.

List subentry password policies

Per-server password policies are part of the DS server configuration. Use the dsconfig command to list, read, and edit them.

Subentry policies are part of the DS directory data. Use the ldapsearch command to list and read them.

The following command lists the subentry password policies under dc=example,dc=com:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDn dc=example,dc=com \
 "(&(objectClass=subEntry)(objectClass=ds-pwp-password-policy))"

dn: cn=NIST inspired policy,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
objectClass: ds-pwp-validator
objectClass: ds-pwp-length-based-validator
objectClass: ds-pwp-dictionary-validator
cn: NIST inspired policy
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA512
ds-pwp-dictionary-data:: <data>
ds-pwp-length-based-min-password-length: 8
ds-pwp-password-attribute: userPassword

Assign password policies

Type To Assign…​

Per-server password policy

Set the ds-pwp-password-policy-dn operational attribute on the user’s account.

Subentry password policy

Use one of the following methods:

  • Set the ds-pwp-password-policy-dn operational attribute on the user’s account.

  • Add the policy to an LDAP subentry whose immediate superior is the root of the subtree containing the accounts.

    For example, add the subentry password policy under ou=People,dc=example,dc=com. It applies to all accounts under ou=People,dc=example,dc=com.

  • Use the capabilities of LDAP subentries. Refine the scope of application by setting the subtreeSpecification attribute on the policy entry.

Do not assign more than one password policy to the same account. Conflicting password policies will yield inconsistent results.

You can review the password policy assigned to an account by reading the pwdPolicySubentry attribute on the entry.

Assign a password policy to a user

  1. Make sure the password administrator has access to manage password policies:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: cn=subentry-write privilege for administrators,dc=example,dc=com
    objectClass: collectiveAttributeSubentry
    objectClass: extensibleObject
    objectClass: subentry
    objectClass: top
    cn: subentry-write privilege for administrators
    ds-privilege-name;collective: subentry-write
    subtreeSpecification: {base "ou=people", specificationFilter
      "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" }
    
    dn: dc=example,dc=com
    changetype: modify
    add: aci
    aci: (target="ldap:///dc=example,dc=com")
     (targetattr = "*||ds-pwp-password-policy-dn||pwdPolicySubentry||subtreeSpecification")
     (version 3.0; acl "Admins can manage entries and password policies"; allow(all)
     groupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
    EOF

    Notice here that the directory superuser, uid=admin, assigns privileges. Any administrator with the privilege-change privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the bypass-acl privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the privilege-change privilege to normal administrator users.

  2. Set the user’s ds-pwp-password-policy-dn attribute as the password administrator:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: uid=newuser,ou=People,dc=example,dc=com
    uid: newuser
    objectClass: person
    objectClass: organizationalPerson
    objectClass: inetOrgPerson
    objectClass: top
    cn: New User
    sn: User
    ou: People
    mail: newuser@example.com
    userPassword: chngthspwd
    ds-pwp-password-policy-dn: cn=NIST inspired policy,dc=example,dc=com
    EOF
  3. Check your work:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     "(uid=newuser)" \
     pwdPolicySubentry
    
    dn: uid=newuser,ou=People,dc=example,dc=com
    pwdPolicySubentry: cn=NIST inspired policy,dc=example,dc=com

Assign a password policy to a group

You can use a collective attribute to assign a password policy. Collective attributes provide a standard mechanism for defining attributes that appear on all the entries in a subtree. For details, see Collective attributes:

  1. Make sure the password administrator has the privilege to write subentries:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=kvaughan,ou=People,dc=example,dc=com
    changetype: modify
    add: ds-privilege-name
    ds-privilege-name: subentry-write
    EOF

    Notice here that the directory superuser, uid=admin, assigns privileges. Any administrator with the privilege-change privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the bypass-acl privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the privilege-change privilege to normal administrator users.

  2. Create a subentry defining the collective attribute that sets the ds-pwp-password-policy-dn attribute for group members' entries:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: cn=Password Policy for Dir Admins,dc=example,dc=com
    objectClass: collectiveAttributeSubentry
    objectClass: extensibleObject
    objectClass: subentry
    objectClass: top
    cn: Password Policy for Dir Admins
    ds-pwp-password-policy-dn;collective: cn=Root Password Policy,cn=Password Policies,cn=config
    subtreeSpecification: { base "ou=People", specificationFilter
      "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)"}
    EOF
  3. Check your work:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     "(uid=kvaughan)" \
     pwdPolicySubentry
    
    dn: uid=kvaughan,ou=People,dc=example,dc=com
    pwdPolicySubentry: cn=Root Password Policy,cn=Password Policies,cn=config

Assign a password policy to a branch

These steps apply only to subentry password policies:

  1. Give an administrator the privilege to write subentries, such as those used for setting password policies:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=kvaughan,ou=People,dc=example,dc=com
    changetype: modify
    add: ds-privilege-name
    ds-privilege-name: subentry-write
    EOF

    Notice here that the directory superuser, uid=admin, assigns privileges. Any administrator with the privilege-change privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the bypass-acl privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the privilege-change privilege to normal administrator users.

  2. Configure a subentry password policy with a subtreeSpecification attribute that defines which accounts are assigned the policy.

    The following example assigns cn=NIST inspired policy to accounts under ou=People,dc=example,dc=com:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: cn=NIST inspired policy,dc=example,dc=com
    changetype: modify
    replace: subtreeSpecification
    subtreeSpecification: { base "ou=people" }
    EOF

    The subtree specification assigns the policy to the people branch with { base "ou=people" }. You could relax the subtree specification value to {} to apply the policy to all entries anywhere underneath dc=example,dc=com. You could further restrict the subtree specification by adding a specificationFilter. For details, see About subentry scope.

  3. Check your work to see that an account under ou=People has the policy:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     "(uid=alutz)" \
     pwdPolicySubentry
    
    dn: uid=alutz,ou=People,dc=example,dc=com
    pwdPolicySubentry: cn=NIST inspired policy,dc=example,dc=com

About subentry scope

LDAP subentries reside with the user data and so the server replicates them. Subentries hold operational data. They are not visible in search results unless explicitly requested. This section describes how a subentry’s subtreeSpecification attribute defines the scope of the subtree that the subentry applies to.

An LDAP subentry’s subtree specification identifies a subset of entries in a branch of the DIT. The subentry scope is these entries. In other words, these are the entries that the subentry affects.

The attribute value for a subtreeSpecification optionally includes the following parameters:

base

Indicates the entry, relative to the subentry’s parent, at the base of the subtree.

By default, the base is the subentry’s parent.

specificationFilter

Indicates an LDAP filter. Entries matching the filter are in scope.

DS servers extend the standard implementation to allow any search filter, not just an assertion about the objectClass attribute.

By default, all entries under the base entry are in scope.

The following illustration shows this for an example collective attribute subentry:

A subentry’s subtreeSpecification defines the scope of the subtree that the subentry applies to.

Notice that the base of ou=People on the subentry cn=Silver Class of Service,dc=example,dc=com indicates that the base entry is ou=People,dc=example,dc=com.

The filter "(classOfService=silver)" means that Kirsten Vaughan and Sam Carter’s entries are in scope. Babs Jensen’s entry, with classOfService: bronze does not match and is therefore not in scope. The ou=People organizational unit entry does not have a classOfService attribute, and so is not in scope, either.

Strong and safe passwords

The difficulty with passwords is that they tend to be relatively easy to guess. Despite decades of advice on how to pick strong passwords, people still routinely pick very weak passwords using common words and phrases or simple variations of them. This makes them extremely easy to guess. Attackers with access to even modest hardware can make billions of guesses per second.

DS servers provide flexible password validation to fit your policies about password content, and to reject weak passwords when users try to save them. It also provides a variety of one-way and reversible password storage schemes. Password strength is a function of both password minimum length, which you can set as part of password policy, and password quality, which requires password validation.

Password validation

When a password is added or updated, a password validator determines whether the server should accept it. Validation does not affect existing passwords.

A user’s password policy specifies which password validators apply whenever that user provides a new password.

Subentry password policies can include attributes of password validator object classes. Each object class derives from the abstract ds-pwp-validator class:

The example that follows shows a password policy that requires new passwords to have at least three of the following four character classes:

  • English lowercase characters (a through z)

  • English uppercase characters (A through Z)

  • Base 10 digits (0 through 9)

  • Punctuation characters (for example, !, $, #, %)

Notice how the character-set values are constructed. The initial 0: means the set is optional, whereas 1: means the set is required:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Policy with character set validation,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
objectClass: ds-pwp-validator
objectClass: ds-pwp-character-set-validator
cn: Policy with character set validation
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-character-set-allow-unclassified-characters: true
ds-pwp-character-set-character-set-ranges: 0:a-z
ds-pwp-character-set-character-set-ranges: 0:A-Z
ds-pwp-character-set-character-set-ranges: 0:0-9
ds-pwp-character-set-character-set: 0:!$%^.#
ds-pwp-character-set-min-character-sets: 3
subtreeSpecification: { base "ou=people", specificationFilter "(uid=bjensen)" }
EOF

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen" \
 --newPassword '!ABcd$%^'

An attempt to set an invalid password fails as shown in the following example:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen" \
 --newPassword hifalutin

The LDAP password modify operation failed: 19 (Constraint Violation)
Additional Information:  The provided new password failed the validation
checks defined in the server: The provided password did not contain characters
from at least 3 of the following character sets or ranges: '!$%^.#', '0-9',
'A-Z', 'a-z'

Per-server password policies use validators that are separate configuration objects. The following example lists the password validators available by default for per-server password policies. By default, no password validators are configured in the default password policy:

$ dsconfig \
 list-password-validators \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Password Validator                  : Type                : enabled
------------------------------------:---------------------:--------
At least 8 characters               : length-based        : true
Attribute Value                     : attribute-value     : true
Character Set                       : character-set       : true
Common passwords                    : dictionary          : true
Dictionary                          : dictionary          : false
Length-Based Password Validator     : length-based        : true
Repeated Characters                 : repeated-characters : true
Similarity-Based Password Validator : similarity-based    : true
Unique Characters                   : unique-characters   : true

For details, see Password Validator.

For an example showing how to test password quality, see Check Password Quality.

Password storage

Password storage schemes, described in Password Storage Scheme, encode new passwords and store the encoded version. When a client application authenticates with the password, the server encodes the plaintext password using the configured storage scheme, and checks whether the result matches the encoded value stored by the server. If the encoded version is appropriately secure, it is difficult to guess the plaintext password from its encoded value.

DS servers offer a variety of reversible and one-way password storage schemes. With a reversible encryption scheme, an attacker who gains access to the server can recover the plaintext passwords. With a one-way hash storage scheme, the attacker who gains access to the server must still crack the password by brute force, encoding passwords over and over to generate guesses until a match is found. If you have a choice, use a one-way password storage scheme.

Some one-way hash functions are not designed specifically for password storage, but also for use in message authentication and digital signatures. Such functions, like those defined in the Secure Hash Algorithm (SHA-1 and SHA-2) standards, are designed for high performance. Because they are fast, they allow the server to perform authentication at high throughput with low response times. However, high-performance algorithms also help attackers use brute force techniques. One estimate in 2017 is that a single GPU can calculate over one billion SHA-512 hashes per second.

Some one-way hash functions are designed to be computationally intensive. Such functions, like PBKDF2, Argon2, and Bcrypt, are designed to be relatively slow, even on modern hardware. This makes them generally less susceptible to brute force attacks.

However, computationally intensive functions reduce authentication throughput and increase response times. With the default number of iterations, the GPU mentioned above might only calculate 100,000 PBKDF2 hashes per second (or 0.01% of the corresponding hashes calculated with SHA-512). If you use these functions, be aware of the potentially dramatic performance impact and plan your deployment accordingly.

Modern hardware and techniques to pre-compute attempts, such as rainbow tables, make it increasingly easy for attackers to crack passwords by brute force. Password storage schemes that use salt make brute force attacks more expensive. In this context, salt is a random value appended to the password before encoding. The salt is then stored with the encoded value and used when comparing an incoming password to the stored password.

Reversible password storage schemes, such as AES and Blowfish, use symmetric keys for encryption.

The following example lists available alternatives, further described in Password Storage Schemes:

$ dsconfig \
 list-password-storage-schemes \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Password Storage Scheme : Type               : enabled
------------------------:--------------------:--------
3DES                    : triple-des         : false
AES                     : aes                : false
Argon2                  : argon2             : true
Base64                  : base64             : false
Bcrypt                  : bcrypt             : true
Blowfish                : blowfish           : false
Clear                   : clear              : false
CRYPT                   : crypt              : false
PBKDF2                  : pbkdf2             : false
PBKDF2-HMAC-SHA256      : pbkdf2-hmac-sha256 : true
PBKDF2-HMAC-SHA512      : pbkdf2-hmac-sha512 : true
PKCS5S2                 : pkcs5s2            : false
Salted SHA-1            : salted-sha1        : false
Salted SHA-256          : salted-sha256      : false
Salted SHA-384          : salted-sha384      : false
Salted SHA-512          : salted-sha512      : false
SCRAM-SHA-256           : scram-sha256       : true
SCRAM-SHA-512           : scram-sha512       : true
SHA-1                   : sha1               : false

As shown in Adjust the default password policy, the default password storage scheme for users is PBKDF2-HMAC-SHA256. When you add users or import user entries with userPassword values in plaintext, the DS server hashes them with the default password storage scheme. The default directory superuser has a different password policy, shown in Assign a password policy to a group. The Root Password Policy uses PBKDF2-HMAC-SHA256 by default.

The choice of default password storage scheme for normal users can significantly impact server performance. Each time a normal user authenticates using simple bind (username/password) credentials, the directory server encodes the user’s password according to the storage scheme in order to compare it with the encoded value in the user’s entry.

Schemes such as Salted SHA-512 call for relatively high-performance encoding. Schemes such as PBKDF2-HMAC-SHA256, which are designed to make the encoding process computationally intensive, reduce the bind throughput that can be achieved on equivalent hardware.

Take this performance impact into consideration when sizing your deployment. With a computationally intensive scheme such as PBKDF2-HMAC-SHA256, make sure the directory service has enough compute power to absorb the additional load.

Password Storage Schemes
Name Type of Algorithm Notes

3DES(1)

Reversible encryption(2)

Triple DES (Data Encryption Standard) in EDE (Encrypt Decrypt Encrypt) mode.

Key size: 168 bits.

AES(1)

Reversible encryption(2)

Advanced Encryption Standard, successor to DES, published by the US National Institute of Standards and Technology (NIST).

Key size: 128 bits.

Argon2

One-way hash

Computationally intensive, memory-hard hashing function.

For default settings, see Additional Password Storage Scheme Settings.

Base64

Reversible encoding

Transfer encoding for representing binary password values in text.

Not intended as a secure storage scheme.

Bcrypt

One-way hash

Computationally intensive hashing function, based on the Blowfish cipher.

Default cost: 12 (2^12 iterations).

Blowfish(1)

Reversible encryption(2)

Public domain cipher designed by Bruce Schneier as a successor to DES.

Key size: 128 bits.

Clear

Cleartext, no encoding

For backwards compatibility and use with certain legacy applications.

Not intended as a secure storage scheme.

CRYPT

One-way hash

Based on the UNIX Crypt algorithm.

For backwards compatibility and use with certain legacy applications.

Not intended as a secure storage scheme.

Default algorithm: unix.

MD5

One-way hash

Based on the MD5 algorithm defined in RFC 1321.

For backwards compatibility and use with certain legacy applications.

Not intended as a secure storage scheme.

PBKDF2

One-way hash

Computationally intensive hashing function, based on PBKDF2 algorithm defined in RFC 8018, 5.2. PBKDF2.

Default iterations: 10000.

The pseudorandom function for the algorithm corresponds to the HMAC based on SHA-1.

PBKDF2-HMAC-SHA256

One-way hash

Computationally intensive hashing function using PBKDF2.

Default iterations: 10000.

The pseudorandom function for the algorithm corresponds to the HMAC based on SHA-2, where the hash function is SHA-256.

PBKDF2-HMAC-SHA512

One-way hash

Computationally intensive hashing function using PBKDF2.

Default iterations: 10000.

The pseudorandom function for the algorithm corresponds to the HMAC based on SHA-2, where the hash function is SHA-512.

PKCS5S2

One-way hash

Computationally intensive hashing function, based on Atlassian’s adaptation of the PBKDF2.

Number of iterations: 10000.

RC4(1)

Reversible encryption(2)

Based on the Rivest Cipher 4 algorithm.

For backwards compatibility and use with certain legacy applications.

Not intended as a secure storage scheme.

Key size: 128 bits.

Salted MD5

One-way hash

Based on MD5, with 64 bits of random salt appended to the plaintext before hashing, and then appended to the hash.

Salted SHA-1

One-way hash

Based on SHA-1, with 64 bits of random salt appended to the plaintext before hashing, and then appended to the hash.

Salted SHA-256

One-way hash

Based on the SHA-256 hash function using 32-bit words and producing 256-bit digests.

SHA-256 is defined in the SHA-2 (Secure Hash Algorithm 2) standard developed by the US National Security Agency (NSA) and published by NIST.

The salt is applied as for Salted SHA-1.

Salted SHA-384

One-way hash

Based on the SHA-384 hash function that effectively truncates the digest of SHA-512 to 384 bits.

SHA-384 is defined in the SHA-2 (Secure Hash Algorithm 2) standard developed by the NSA and published by NIST.

The salt is applied as for Salted SHA-1.

Salted SHA-512

One-way hash

Based on the SHA-512 hash function using 64-bit words and producing 512-bit digests.

SHA-512 is defined in the SHA-2 (Secure Hash Algorithm 2) standard developed by the NSA and published by NIST.

The salt is applied as for Salted SHA-1.

SCRAM-SHA-256

One-way hash

For use with the standard SASL Salted Challenge Response Authentication Mechanism (SCRAM), named SCRAM-SHA-256.

A SASL SCRAM mechanism provides a secure alternative to transmitting plaintext passwords during binds. It is an appropriate replacement for DIGEST-MD5 and CRAM-MD5.

With a SCRAM SASL bind, the client must demonstrate proof that it has the original plaintext password. During the SASL bind, the client must perform computationally intensive processing to prove that it has the plaintext password. This computation is like what the server performs for PBKDF2, but the password is not communicated during the bind.

Once the server has stored the password, the client pays the computational cost to perform the bind. The server only pays a high computational cost when the password is updated, for example, when an entry with a password is added or during a password modify operation. A SASL SCRAM mechanism therefore offers a way to offload the high computational cost of secure password storage to client applications during authentication.

Passwords storage using a SCRAM storage scheme is compatible with simple binds and SASL PLAIN binds. When a password is stored using a SCRAM storage scheme, the server pays the computational cost to perform the bind during a simple bind or SASL PLAIN bind.

The SCRAM password storage scheme must match the SASL SCRAM mechanism used for authentication. In other words, SASL SCRAM-SHA-256 requires a SCRAM-SHA-256 password storage scheme. SASL SCRAM-SHA-512 requires a SCRAM-SHA-512 password storage scheme.

Default iterations: 10000.

The pseudorandom function for the algorithm corresponds to the HMAC based on SHA-2, where the hash function is SHA-256.

SCRAM-SHA-512

One-way hash

Like SCRAM-SHA-256, but the hash function is SHA-512. The corresponding SASL mechanism is named SCRAM-SHA-512.

SHA-1

One-way hash

SHA-1 (Secure Hash Algorithm 1) standard developed by the NSA and published by NIST.

Not intended as a secure storage scheme.

(1) Reversible encryption schemes are deprecated.

(2) When you configure a reversible password storage scheme, enable the adminRoot backend, and configure a replication domain for cn=admin data. These additional steps let the replicas store and replicate the secret keys for password encryption.

Password storage schemes listed in the following table have additional configuration settings.

Additional Password Storage Scheme Settings
Scheme Setting Description

Argon2

argon2-iterations

The number of iterations to perform. Default: 2.

argon2-memory

The amount of memory to use for a single hash, expressed in kibibytes. Default: 15360.

argon2-migration-memory

The memory requirement expected during an Argon2 password migration. Ignored if less than argon2-memory. Default: 0.

argon2-parallelism

The number of threads that work in parallel to compute a hash. Default: 1.

argon2-variant

The variant of Argon2 algorithm to use (I, D, or ID). Default: ID.

argon2-length

The length of the resulting hash. Default: 32.

argon2-salt-length

The length of the salt used when hashing passwords. Default: 16.

rehash-policy

Whether the server should rehash passwords after the cost has been changed. Default: never.

Bcrypt

bcrypt-cost

The cost parameter specifies a key expansion iteration count as a power of two.

A default value of 12 (212 iterations) is considered in 2016 as a reasonable balance between responsiveness and security for regular users.

rehash-policy

Whether the server should rehash passwords after the cost has been changed. Default: never.

Crypt

crypt-password-storage-encryption-algorithm

Specifies the crypt algorithm to use to encrypt new passwords.

The following values are supported:

unix

The password is encrypted with the weak Unix crypt algorithm.

This is the default setting.

md5

The password is encrypted with the BSD MD5 algorithm and has a $1$ prefix.

sha256

The password is encrypted with the SHA256 algorithm and has a $5$ prefix.

sha512

The password is encrypted with the SHA512 algorithm and has a $6$ prefix.

PBKDF2

PBKDF2-HMAC-SHA256

PBKDF2-HMAC-SHA512

pbkdf2-iterations

The number of algorithm iterations.

The default is 10000.

rehash-policy

Whether the server should rehash passwords after the cost has been changed. Default: never.

SCRAM

SCRAM-SHA-256

SCRAM-SHA-512

scram-iterations

The number of algorithm iterations.

The default is 10000.

You change the default password policy storage scheme for users by changing the applicable password policy:

$ dsconfig \
 set-password-policy-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --policy-name "Default Password Policy" \
 --set default-password-storage-scheme:PBKDF2-HMAC-SHA512 \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Notice that the change in default password storage scheme does not cause the DS server to update any stored password values. By default, the server only stores a password with the new storage scheme the next time the password is changed.

For subentry password policies, set the ds-pwp-default-password-storage-scheme attribute to the common name of an enabled password storage scheme. To list the names of enabled password storage schemes, use the dsconfig list-password-storage-schemes command. The name appears in the first column of the output. The third column shows whether the scheme is enabled.

DS servers prefix passwords with the scheme used to encode them, which means it is straightforward to see which password storage scheme is used. After the default password storage scheme is changed to PBKDF2-HMAC-SHA512, old user passwords remain encoded with PBKDF2-HMAC-SHA256:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword hifalutin \
 --baseDN dc=example,dc=com \
 "(uid=bjensen)" \
 userPassword

dn: uid=bjensen,ou=People,dc=example,dc=com
userPassword: {PBKDF2-HMAC-SHA256}10:<hash>

When the password is changed, the new default password storage scheme takes effect:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen" \
 --newPassword changeit

The LDAP password modify operation was successful

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword changeit \
 --baseDN dc=example,dc=com \
 "(uid=bjensen)" \
 userPassword

dn: uid=bjensen,ou=People,dc=example,dc=com
userPassword: {PBKDF2-HMAC-SHA512}10000:<hash>

When you change the password storage scheme for users, realize that the user passwords must change in order for the DS server to encode them with the chosen storage scheme. If you are changing the storage scheme because the old scheme was too weak, then you no doubt want users to change their passwords anyway.

If, however, the storage scheme change is not related to vulnerability, use the deprecated-password-storage-scheme property in per-server password policies, or the ds-pwp-deprecated-password-storage-scheme attribute in subentry password policies. This setting causes the DS server to store the password in the new format after successful authentication. This makes it possible to do password migration for active users as users gradually change their passwords:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDN dc=example,dc=com \
 "(uid=kvaughan)" \
 userPassword

dn: uid=kvaughan,ou=People,dc=example,dc=com
userPassword: {PBKDF2-HMAC-SHA256}10:<hash>

$ dsconfig \
 set-password-policy-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --policy-name "Default Password Policy" \
 --set deprecated-password-storage-scheme:PBKDF2-HMAC-SHA256 \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDN dc=example,dc=com \
 "(uid=kvaughan)" \
 userPassword

dn: uid=kvaughan,ou=People,dc=example,dc=com
userPassword: {PBKDF2-HMAC-SHA512}10000:<hash>

Notice that with deprecated-password-storage-scheme set appropriately, Kirsten Vaughan’s password was hashed again after she authenticated successfully.

Password generation

DS servers use password generators when responding with a generated password for the LDAP Password Modify extended operation. A directory administrator resetting a user’s password has the server generate the new password, and the server sends the new password in the response:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen"

The LDAP password modify operation was successful
Generated Password:  <random>

The default password policy uses the Random Password Generator, described in Random Password Generator:

$ dsconfig \
 get-password-policy-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --policy-name "Default Password Policy" \
 --property password-generator \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Property           : Value(s)
-------------------:--------------------------
password-generator : Random Password Generator

$ dsconfig \
 get-password-generator-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --generator-name "Random Password Generator" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Property               : Value(s)
-----------------------:-------------------------------------------------------
enabled                : true
password-character-set : alphanum:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
                       : TUVWXYZ0123456789
password-format        : alphanum:10

Notice that the default configuration for the Random Password Generator sets the password-character-set property, and references the settings in the password-format property. Generated passwords have eight characters: three from the alpha set, followed by two from the numeric set, followed by three from the alpha set. The password-character-set name must be ASCII.

Subentry password policies configure ds-pwp-random-generator object class attributes. The following example creates a password with password generation, and demonstrates its use:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Policy with random password generation,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
objectClass: ds-pwp-validator
objectClass: ds-pwp-length-based-validator
objectClass: ds-pwp-random-generator
cn: Policy with random password generation
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-random-password-character-set: alpha:ABCDEFGHIJKLMNOPQRSTUVWabcdefghijklmnopqrstuvwxyz
ds-pwp-random-password-character-set: punct:,.!&+=-_
ds-pwp-random-password-character-set: numeric:0123456789
ds-pwp-random-password-format: alpha:3,punct:1,numeric:2,punct:2,numeric:3,alpha:3,punct:2
ds-pwp-length-based-min-password-length: 8
subtreeSpecification: { base "ou=people" }
EOF

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen"

The LDAP password modify operation was successful
Generated Password:  <random>

When configuring both password validators and password generators, make sure the generated passwords are acceptable to the validator. In this case, the minimum length is less than the generated password length, for example.

Sample password policies

Lock accounts after repeated bind failures

To help you prevent brute-force attacks, where an attacker tries many passwords in the hope of eventually guessing correctly, DS password policies support configurable account lockout. This feature is an important part of a secure password policy.

When you configure account lockout as part of password policy, DS servers lock an account after the specified number of consecutive authentication failures. Account lockout is not transactional across all replicas in a deployment. Global account lockout occurs as soon as the authentication failure times have been replicated.

The following commands demonstrate a subentry password policy that locks accounts for five minutes after three consecutive bind failures. With this policy, the directory server records failure times, and slowly discards them. As a result, a brute-force attack is hopefully too slow to be effective, but no administrative action is needed when a user temporarily forgets or mistypes their password.

Once an account is locked, binds continue to fail for the lockout period, even if the credentials are correct. An account administrator can use the manage-account command to view the account status, and to change it if necessary:

Show example commands
# Set the password policy:
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Lock After Repeated Bind Failures,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Lock After Repeated Bind Failures
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-lockout-duration: 5 m
ds-pwp-lockout-failure-count: 3
ds-pwp-lockout-failure-expiration-interval: 2 m
subtreeSpecification: { base "ou=people", specificationFilter "(objectClass=posixAccount)" }
EOF

# Attempt to bind three times using the wrong password:
$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword wrongPassword \
 --baseDn dc=example,dc=com \
 "(uid=bjensen)"

The LDAP bind request failed: 49 (Invalid Credentials)

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword wrongPassword \
 --baseDn dc=example,dc=com \
 "(uid=bjensen)"

The LDAP bind request failed: 49 (Invalid Credentials)

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword wrongPassword \
 --baseDn dc=example,dc=com \
 "(uid=bjensen)"

The LDAP bind request failed: 49 (Invalid Credentials)

# Observe the results:
$ manage-account \
 get-all \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --targetDN uid=bjensen,ou=people,dc=example,dc=com \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin

Password Policy DN:  cn=Lock After Repeated Bind Failures,dc=example,dc=com
Seconds Until Authentication Failure Unlock:  <seconds>

Enforce regular password changes

The following commands configure a subentry password policy that sets age limits on passwords, requiring that users change their passwords at least every 13 weeks, but not more often than every 4 weeks. The policy also sets the number of passwords to keep in the password history of the entry, preventing users from reusing the same password on consecutive changes:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Enforce Regular Password Changes,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Enforce Regular Password Changes
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-max-password-age: 13 w
ds-pwp-min-password-age: 4 w
ds-pwp-password-history-count: 7
subtreeSpecification: { base "ou=people" }
EOF

Track last login time

The following command configures a subentry password policy that keeps track of the last successful login:

  1. Create the password policy to write the timestamp to the attribute on successful login:

    $ dsconfig \
     create-password-policy \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "Track Last Login Time" \
     --type password-policy \
     --set default-password-storage-scheme:PBKDF2-HMAC-SHA256 \
     --set password-attribute:userPassword \
     --set last-login-time-attribute:ds-last-login-time \
     --set last-login-time-format:"yyyyMMddHH'Z'" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

Deprecate a password storage scheme

The following commands configure a subentry password policy for deprecating a password storage scheme. This policy uses elements from Enforce regular password changes. The DS server applies the new password storage scheme to re-encode passwords:

  • When they change.

  • When the user successfully binds with the correct password, and the password is currently hashed with a deprecated scheme.

$ dsconfig \
 set-password-storage-scheme-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --scheme-name "Salted SHA-512" \
 --set enabled:true \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Deprecate a Password Storage Scheme,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Deprecate a Password Storage Scheme
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-deprecated-password-storage-scheme: Salted SHA-512
ds-pwp-max-password-age: 13 w
ds-pwp-min-password-age: 4 w
ds-pwp-password-history-count: 7
subtreeSpecification: { base "ou=people" }
EOF

Lock idle accounts

The following commands configure a subentry password policy that locks accounts idle for more than 13 weeks. This policy extends the example from Track last login time. The DS server must track last successful login time to calculate how long the account has been idle:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Lock Idle Accounts,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Lock Idle Accounts
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-idle-lockout-interval: 13 w
ds-pwp-last-login-time-attribute: ds-last-login-time
ds-pwp-last-login-time-format: yyyyMMddHH'Z'
subtreeSpecification: { base "ou=people" }
EOF

Allow log in to change an expired password

The following commands configure a subentry password policy that lets users log in twice with an expired password to set a new password:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Allow Grace Login,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Allow Grace Login
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-grace-login-count: 2
subtreeSpecification: { base "ou=people" }
EOF

Require password change on add or reset

The following commands configure a subentry password policy that requires new users to change their password after logging in for the first time. This policy also requires users to change their password after it is reset:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Require Password Change on Add or Reset,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
cn: Require Password Change on Add or Reset
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
ds-pwp-force-change-on-add: true
ds-pwp-force-change-on-reset: true
subtreeSpecification: { base "ou=people" }
EOF

About password policies

DS password policies govern passwords, account lockout, and account status notification.

DS servers support per-server password policies stored in the configuration, and subentry password policies stored in the (replicated) directory data:

Type Notes
  • Use for default policies, and policies for top-level administrative accounts.

  • You must manually apply policy updates to each replica server configuration.

  • Updates require write access to the server configuration.

  • Use for all user accounts stored in application data.

  • Replication applies each policy update to all replicas.

  • Updates require the subentry-write privilege, and ACIs to write the policy.

Per-server policies are not replicated
Figure 1. Per-Server and Subentry Password Policies

Per-server password policies

You manage per-server password policies with the dsconfig command. When changing a per-server policy, you must update each replica in your deployment.

By default, there are two per-server password policies:

  • The Default Password Policy for users.

  • The Root Password Policy for the directory superuser, uid=admin.

The following example displays the default per-server password policy for users:

$ dsconfig \
 get-password-policy-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --policy-name "Default Password Policy" \
 --advanced \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Property                                  : Value(s)
------------------------------------------:------------------------------------
account-status-notification-handler       : -
allow-expired-password-changes            : false
allow-multiple-password-values            : false
allow-pre-encoded-passwords               : false
allow-user-password-changes               : true
default-password-storage-scheme           : PBKDF2-HMAC-SHA256
deprecated-password-storage-scheme        : -
expire-passwords-without-warning          : false
force-change-on-add                       : false
force-change-on-reset                     : false
grace-login-count                         : 0
idle-lockout-interval                     : 0 s
java-class                                : org.opends.server.core.PasswordPoli
                                          : cyFactory
last-login-time-attribute                 : -
last-login-time-format                    : -
lockout-duration                          : 0 s
lockout-failure-count                     : 0
lockout-failure-expiration-interval       : 0 s
max-password-age                          : 0 s
max-password-reset-age                    : 0 s
min-password-age                          : 0 s
password-attribute                        : userPassword
password-change-requires-current-password : false
password-expiration-warning-interval      : 5 d
password-generator                        : Random Password Generator
password-history-count                    : 0
password-history-duration                 : 0 s
password-validator                        : At least 8 characters, Common
                                          : passwords
previous-last-login-time-format           : -
require-change-by-time                    : -
require-secure-authentication             : true
require-secure-password-changes           : true
skip-validation-for-administrators        : false
state-update-failure-policy               : reactive

For detailed descriptions of each property, see Password Policy.

These settings are configured by default:

  • When granted access, users can change their passwords.

  • DS servers use the standard userPassword attribute to store passwords.

    DS servers also support the alternative standard authPassword attribute.

  • When you import LDIF with userPassword values, DS servers apply a one-way hash to the passwords before storing them.

    When a user provides a password value during a bind, for example, the server hashes the incoming password, and compares it with the stored value. This mechanism helps prevent even the directory superuser from recovering the plain text password:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)" \
     userpassword
    
    dn: uid=bjensen,ou=People,dc=example,dc=com
    userpassword: {PBKDF2-HMAC-SHA256}10:<hash>
  • The server can set a random password when a password administrator resets a user’s password.

Many capabilities are not set by default:

  • No lockout.

  • No password expiration.

  • No password validator to check that passwords contain the appropriate mix of characters.

If the directory service enforces password policy, configure at least the default password policy accordingly.

DS subentry password policies

You manage password policies as LDAP subentries in the application data. Replication applies updates to subentry password policies to all other replicas. Password policy administrators do not need access to the server configuration.

The DS subentry password policy entries have the object classes:

  • ds-pwp-password-policy for most password policy features.

  • A set of password validator object classes for specific validators that derive from the abstract ds-pwp-validator class for password validation configuration.

  • ds-pwp-random-generator for password generation on reset.

The following tables describe password policy attributes per object class:

ds-pwp-password-policy Attributes
Attribute Description

ds-pwp-password-attribute (required)

The attribute type used to hold user passwords.

ds-pwp-default-password-storage-scheme (required)

Names of enabled password storage schemes used to encode plaintext passwords.

Default: PBKDF2-HMAC-SHA256.

cn

Name of the password policy

ds-pwp-allow-user-password-changes

Whether users can change their passwords, assuming access control allows it.

Default: true.

ds-pwp-account-status-notification-handler

Names of enabled account status notification handlers to use with this policy.

Use the dsconfig list-account-status-notification-handlers command. The first column of the output shows the names. The third column shows whether the handler is enabled.

ds-pwp-allow-expired-password-changes

Whether the user can change an expired password with the password modify extended operation.

Default: false.

ds-pwp-allow-multiple-password-values

Whether user entries can have multiple distinct passwords. Any password is sufficient to authenticate.

Default: false.

ds-pwp-allow-pre-encoded-passwords

Whether users can change their passwords by providing a pre-encoded value.

Default: false.

ds-pwp-deprecated-password-storage-scheme

Names of deprecated password storage schemes for this policy.

On successful authentication, encode the password with the default.

ds-pwp-expire-passwords-without-warning

Whether to allow a user’s password to expire even if that user has never seen an expiration warning notification.

Default: false.

ds-pwp-force-change-on-add

Whether users are forced to change their passwords upon first authentication after their accounts are added.

Default: false.

ds-pwp-force-change-on-reset

Whether users are forced to change their passwords after password reset by an administrator. For this purpose, anyone with permission to change a given user’s password other than that user is an administrator.

Default: false.

ds-pwp-grace-login-count

Number of grace logins that a user is allowed after the account has expired so the user can update their password.

Default: 0 (disabled).

ds-pwp-idle-lockout-interval

Maximum number of seconds that an account may remain idle (the associated user does not authenticate to the server) before that user is locked out. Requires maintaining a last login time attribute.

Default: 0 seconds (inactive).

ds-pwp-last-login-time-attribute

Name or OID of the attribute type that is used to hold the last login time for users.

Default: The last-login-time-attribute setting from the default password policy. By default, last-login-time-attribute is not set.

ds-pwp-last-login-time-format

Format string that is used to generate the last login time value for users.

The format string must match the syntax of the ds-pwp-last-login-time-attribute attribute, and must be a valid format string for the java.text.SimpleDateFormat class.

Default: yyyyMMddHHmmss’Z'.

ds-pwp-lockout-duration

Duration that an account is locked after too many authentication failures.

Default: 0 seconds (account remains locked until the administrator resets the password).

ds-pwp-lockout-failure-count

Maximum number of authentication failures that a user is allowed before the account is locked out.

Default: 0 (disabled).

ds-pwp-lockout-failure-expiration-interval

Duration before an authentication failure is no longer counted against a user for the purposes of account lockout.

Default: 0 seconds (never expire).

ds-pwp-max-password-age

Duration that a user can continue using the same password before it must be changed (the password expiration interval).

Default: 0 seconds (passwords never expire).

ds-pwp-max-password-reset-age

Maximum number of seconds that users have to change passwords after they have been reset by an administrator before they become locked.

Default: 0 seconds.

ds-pwp-min-password-age

Minimum duration after a password change before the user is allowed to change the password again.

Default: 0 seconds.

ds-pwp-password-change-requires-current-password

Whether user password changes must include the user’s current password before the change is allowed. This can be done with either the password modify extended operation, or a modify operation using delete and add.

Default: false.

ds-pwp-password-expiration-warning-interval

Duration before a user’s password actually expires that the server begins to include warning notifications in bind responses for that user.

Default: 5 days.

ds-pwp-password-history-count

Maximum number of former passwords to maintain in the password history.

A value of zero indicates that either no password history is to be maintained if the password history duration has a value of zero seconds, or that there is no maximum number of passwords to maintain in the history if the password history duration has a value greater than zero seconds.

Default: 0.

ds-pwp-password-history-duration

Maximum number of seconds that passwords remain in the password history.

Default: 0 seconds (inactive).

ds-pwp-previous-last-login-time-format

Format string(s) that might have been used with the last login time at any point in the past for users associated with the password policy.

Default: yyyyMMddHHmmss’Z'.

ds-pwp-require-change-by-time

Time by which all users with the associated password policy must change their passwords. Specified in generalized time form.

ds-pwp-require-secure-authentication

Whether users with the associated password policy are required to authenticate in a secure manner.

Default: false.

ds-pwp-require-secure-password-changes

Whether users with the associated password policy are required to change their password in a secure manner that does not expose the credentials.

Default: false.

ds-pwp-skip-validation-for-administrators

Whether passwords set by administrators are allowed to bypass the password validation process.

Default: false.

ds-pwp-state-update-failure-policy

How the server deals with the inability to update password policy state information during an authentication attempt.

One of the following:

  • ignore: If a bind attempt would otherwise be successful, then do not reject it if a problem occurs while attempting to update the password policy state information for the user.

  • proactive: Proactively reject any bind attempt if it is known ahead of time that it would not be possible to update the user’s password policy state information.

  • reactive (default): Even if a bind attempt would otherwise be successful, reject it if a problem occurs while attempting to update the password policy state information for the user.

ds-pwp-attribute-value-validator Attributes
Attribute Description

ds-pwp-attribute-value-test-reversed-password

Whether this password validator should test the reversed value of the provided password as well as the order in which it was given.

Default: false.

ds-pwp-attribute-value-match-attribute

Name(s) of the attribute(s) whose values should be checked to determine whether they match the provided password.

If no values are provided, then the server checks if the proposed password matches the value of any user attribute in the user’s entry. The server does not check values of operational attributes.

ds-pwp-attribute-value-check-substrings

Whether this password validator is to match portions of the password string against attribute values.

When false, the server checks whether the entire password matches any user attribute values. When true, the server checks whether the password contains any user attribute values.

Consider the case of Babs Jensen (uid: bjensen) changing her password. The following table describes the effects of the settings:

Setting New Password Password Modification Result

ds-pwp-attribute-value-check-substrings: false

bjense

Success

ds-pwp-attribute-value-check-substrings: false

bjensen

Failure: 19 (Constraint Violation)

ds-pwp-attribute-value-check-substrings: false

bjensens

Success

ds-pwp-attribute-value-check-substrings: true

bjense

Success

ds-pwp-attribute-value-check-substrings: true

bjensen

Failure: 19 (Constraint Violation)

ds-pwp-attribute-value-check-substrings: true

bjensens

Failure: 19 (Constraint Violation)

In summary:

  • bjense is allowed in both cases because the password does not contain any of the attribute values in Babs’s entry.

  • bjensen is rejected in both cases because the password exactly matches and contains Babs’s user ID.

  • bjensens is allowed when the setting is false because the password does not exactly match, and rejected when the setting is true because the password contains Babs’s user ID.

Default: false.

ds-pwp-attribute-value-min-substring-length

The minimal length of the substring within the password when substring checking is enabled.

Default: 0.

ds-pwp-character-set-validator Attributes
Attribute Description

ds-pwp-character-set-allow-unclassified-characters

Whether this password validator allows passwords to contain characters outside of any of the user-defined character sets and ranges.

Default: false.

ds-pwp-character-set-min-character-sets

Minimum number of character sets and ranges that a password must contain.

Use in conjunction with optional character sets and ranges (those requiring zero characters). The value must include any mandatory character sets and ranges (those requiring greater than zero characters). This is useful in situations where a password must contain characters from mandatory character sets and ranges, and characters from at least N optional character sets and ranges. For example, it is quite common to require that a password contains at least one non-alphanumeric character as well as characters from two alphanumeric character sets (lower-case, upper-case, digits). In this case, this property should be set to 3.

ds-pwp-character-set-character-set

A character set containing characters that a password may contain, and a value indicating the minimum number of characters required from that set.

Each value must be an integer (indicating the minimum required characters from the set which may be zero, indicating that the character set is optional) followed by a colon and the characters to include in that set. For example, 3:abcdefghijklmnopqrstuvwxyz indicates that a user password must contain at least three characters from the set of lowercase ASCII letters.

Multiple character sets can be defined in separate values, although no character can appear in more than one character set.

ds-pwp-character-set-character-set-ranges

A character range containing characters that a password may contain, and a value indicating the minimum number of characters required from that range. Each value must be an integer (indicating the minimum required characters from the range which may be zero, indicating that the character range is optional) followed by a colon and one or more range specifications.

A range specification is 3 characters: the first character allowed, a minus, and the last character allowed. For example, 3:A-Za-z0-9. The ranges in each value should not overlap, and the characters in each range specification should be ordered.

ds-pwp-dictionary-validator Attributes
Attribute Description

ds-pwp-dictionary-data (required)

A gzipped password dictionary, one word per line.

This is a single-valued attribute.

ds-pwp-dictionary-case-sensitive-validation

Whether this password validator should treat password characters in a case-sensitive manner.

Default: false.

ds-pwp-dictionary-check-substrings

Whether this password validator is to match portions of the password string against dictionary words.

Default: false (match only the entire password against dictionary words).

ds-pwp-dictionary-min-substring-length

The minimal length of the substring within the password in case substring checking is enabled.

Default: 0.

ds-pwp-dictionary-test-reversed-password

Whether this password validator should test the reversed value of the provided password as well as the order in which it was given.

Default: false.

ds-pwp-length-based-validator Attributes
Attribute Description

ds-pwp-length-based-max-password-length

Minimum plaintext password length.

Default: 0 (undefined).

ds-pwp-length-based-min-password-length

Minimum plaintext password length.

Default: 6.

ds-pwp-repeated-characters-validator Attributes
Attribute Description

ds-pwp-repeated-characters-max-consecutive-length

The maximum number of times that any character can appear consecutively in a password value.

Default: 0 (no maximum limit is enforced).

ds-pwp-repeated-characters-case-sensitive-validation

Whether this password validator should treat password characters in a case-sensitive manner.

Default: false.

ds-pwp-similarity-based-validator Attributes
Attribute Description

ds-pwp-similarity-based-min-password-difference

The minimum difference the new and old password.

The implementation uses the Levenshtein Distance algorithm to determine the minimum number of changes (where a change may be inserting, deleting, or replacing a character) to transform one string into the other. It can prevent users from making only minor changes to their current password when setting a new password. Note that for this password validator to be effective, it must have access to the user’s current password. Therefore, if this password validator is to be enabled, also set ds-pwp-password-change-requires-current-password: true.

Default: 0 (no difference between passwords is acceptable).

ds-pwp-unique-characters-validator Attributes
Attribute Description

ds-pwp-unique-characters-case-sensitive-validation

Whether this password validator should treat password characters in a case-sensitive manner.

Default: false.

ds-pwp-unique-characters-min-unique-characters

The minimum number of unique characters that a password will be allowed to contain.

Default: 0 (no minimum value is enforced).

ds-pwp-random-generator Attributes
Attribute Description

ds-pwp-random-password-character-set (required)

Named character sets. The format of the character set is the name of the set followed by a colon and the characters that are in that set. For example, the value alpha:abcdefghijklmnopqrstuvwxyz defines a character set named alpha containing all of the lower-case ASCII alphabetic characters.

ds-pwp-random-password-format (required)

The format to use for the generated password. The value is a comma-delimited list of elements in which each of those elements is comprised of the name of a character set defined in the password-character-set property, a colon, and the number of characters to include from that set. For example, a value of alpha:3,numeric:2,alpha:3 generates an 8-character password in which the first three characters are from the alpha set, the next two are from the numeric set, and the final three are from the alpha set.

Interoperable subentry password policies

DS servers support the Internet-Draft, Password Policy for LDAP Directories (version 09). The password policies are expressed as LDAP subentries with objectClass: pwdPolicy. An Internet-Draft password policy effectively overrides settings in the default per-server password policy for users, inheriting settings that it does not support or does not include from the per-server password policy.

The following table describes Internet-Draft policy attributes:

pwdPolicy Attributes
Attribute Description

pwdAttribute (required)

The attribute type used to hold user passwords.

pwdAllowUserChange

Whether users can change their passwords.

Default: true.

pwdExpireWarning

Maximum number of seconds before a user’s password actually expires that the server begins to include warning notifications in bind responses for that user.

Default: 432000 seconds.

pwdFailureCountInterval

Length of time before an authentication failure is no longer counted against a user for the purposes of account lockout.

Default: 0 seconds (never expire).

pwdGraceAuthNLimit

Number of grace logins that a user is allowed after the account has expired so the user can update their password.

Default: 0 (disabled).

pwdInHistory

Maximum number of former passwords to maintain in the password history.

Default: 0 (disabled).

pwdLockoutDuration

Number of seconds that an account is locked after too many authentication failures.

Default: 0 seconds (account remains locked indefinitely).

pwdMaxAge

Maximum number of seconds that a user can continue using the same password before it must be changed (the password expiration interval).

Default: 0 seconds (disabled).

pwdMaxFailure

Maximum number of authentication failures that a user is allowed before the account is locked out.

Default: 0.

pwdMinAge

Minimum number of seconds after a password change before the user is allowed to change the password again.

Default: 0 seconds (disabled).

pwdMustChange

Whether users are forced to change their passwords after password reset by an administrator.

Default: false.

pwdSafeModify

Whether user password changes must use the password modify extended operation, and must include the user’s current password before the change is allowed.

Default: false.

The following table lists Internet-Draft policy attributes that override the per-server policy properties:

Internet-Draft Policy Attribute Overrides This Server Policy Property

pwdAllowUserChange

allow-user-password-changes

pwdMustChange

force-change-on-reset

pwdGraceAuthNLimit

grace-login-count

pwdLockoutDuration

lockout-duration

pwdMaxFailure

lockout-failure-count

pwdFailureCountInterval

lockout-failure-expiration-interval

pwdMaxAge

max-password-age

pwdMinAge

min-password-age

pwdAttribute

password-attribute

pwdSafeModify

password-change-requires-current-password

pwdExpireWarning

password-expiration-warning-interval

pwdInHistory

password-history-count

DS servers ignore the following Internet-Draft password policy attributes:

  • pwdCheckQuality, because DS servers have password validators.

  • pwdMinLength, because you can use a length-based password validator instead.

  • pwdLockout, because DS servers use other lockout-related password policy attributes.

Internet-Draft based password policies inherit these settings from the default per-server policy for users:

  • account-status-notification-handlers

  • allow-expired-password-changes

  • allow-multiple-password-values

  • allow-pre-encoded-passwords

  • default-password-storage-schemes

  • deprecated-password-storage-schemes

  • expire-passwords-without-warning

  • force-change-on-add

  • idle-lockout-interval

  • last-login-time-attribute

  • last-login-time-format

  • max-password-reset-age

  • password-generator

  • password-history-duration

  • password-validators

  • previous-last-login-time-formats

  • require-change-by-time

  • require-secure-authentication

  • require-secure-password-changes

  • skip-validation-for-administrators

  • state-update-failure-policy