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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)"
    dn: uid=bjensen,ou=People,dc=example,dc=com
    objectClass: person
    objectClass: cos
    objectClass: jsonObject
    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
    json: {"access_token":"123","expires_in":59,"token_type":"Bearer","refresh_token":"456"}
    l: San Francisco
    mail: bjensen@example.com
    mailQuota: 1 GB
    manager: uid=trigden, ou=People, dc=example,dc=com
    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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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.

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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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".

Assign Password Policies

TypeTo 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.

Important

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 as shown in the examples that follow.

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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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 are replicated. 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:

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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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.

Warning

Some one-way hash functions are designed to be computationally expensive. Such functions, like PBKDF2 and Bcrypt, are designed to be relatively slow even on modern hardware. This makes them generally less susceptible to brute force attacks. However, computationally expensive 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. Do not use functions like Bcrypt for any accounts that are used for frequent, short-lived connections.

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 \
 --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
 --no-prompt
Password Storage Scheme : Type               : enabled
------------------------:--------------------:--------
3DES                    : triple-des         : false
AES                     : aes                : false
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.

Tip

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 expensive, reduce the bind throughput that can be achieved on equivalent hardware.

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

Password Storage Schemes
NameType of AlgorithmNotes
3DES[a]Reversible encryption[b]

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

Key size: 168 bits.

AES[a]Reversible encryption[b]

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

Key size: 128 bits.

Base64Reversible encoding

Transfer encoding for representing binary password values in text.

Not intended as a secure storage scheme.

BcryptOne-way hash

Computationally intensive hashing function, based on the Blowfish cipher.

Default cost: 12 (2^12 iterations).

Blowfish[a]Reversible encryption[b]

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

Key size: 128 bits.

ClearCleartext, no encoding

For backwards compatibility and use with certain legacy applications.

Not intended as a secure storage scheme.

CRYPTOne-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.

MD5One-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.

PBKDF2One-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-SHA256One-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-SHA512One-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.

PKCS5S2One-way hash

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

Number of iterations: 10000.

RC4[a]Reversible encryption[b]

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 MD5One-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-1One-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-256One-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-384One-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-512One-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-256One-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-512One-way hash

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

SHA-1One-way hash

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

Not intended as a secure storage scheme.

[a] Reversible encryption schemes are deprecated.

[b] 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
SchemeSettingDescription

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.

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. NIST recommends at least 1000.

The default is 10000.

rehash-policy

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

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, as shown in the following example:

$ 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 \
 --trustStorePasswordFile /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 that 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 \
 --trustStorePasswordFile /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-SHA512}10000:<hash>

When the password is changed, the new default password storage scheme takes effect, as shown in the following example:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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}10000:<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 \
 --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
 --no-prompt
$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password \
 --authzID "u:bjensen"
The LDAP password modify operation was successful
Generated Password:  <random>

For details, see "ds-pwp-random-generator Attributes".

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

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 \
 --trustStorePasswordFile /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 commands configure a subentry password policy that keeps track of the last successful login:

  1. Set up an attribute to which the DS directory server can write a timestamp value on successful login.

    For additional information, see "Active Accounts":

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: cn=schema
    changetype: modify
    add: attributeTypes
    attributeTypes: ( lastLoginTime-oid
      NAME 'lastLoginTime'
      DESC 'Last time the user logged in'
      EQUALITY generalizedTimeMatch
      ORDERING generalizedTimeOrderingMatch
      SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
      SINGLE-VALUE
      NO-USER-MODIFICATION
      USAGE directoryOperation
      X-ORIGIN 'DS example documentation' )
    EOF
  2. 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:lastLoginTime \
     --set last-login-time-format:"yyyyMMddHH'Z'" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePasswordFile /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 \
 --trustStorePasswordFile /path/to/opendj/config/keystore.pin \
 --no-prompt
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePasswordFile /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. You must first add the lastLoginTime attribute type in order for the DS server to accept this new password policy:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePasswordFile /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: lastLoginTime
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 \
 --trustStorePasswordFile /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 \
 --trustStorePasswordFile /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:

TypeNotes

"Per-Server Password Policies"

  • 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.

"DS Subentry Password Policies"

  • 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 and Subentry Password Policies
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 \
 --trustStorePasswordFile /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 \
     --trustStorePasswordFile /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}10000:<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
AttributeDescription

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 considered 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
AttributeDescription

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:

SettingNew PasswordPassword Modification Result
ds-pwp-attribute-value-check-substrings: falsebjenseSuccess
ds-pwp-attribute-value-check-substrings: falsebjensenFailure: 19 (Constraint Violation)
ds-pwp-attribute-value-check-substrings: falsebjensensSuccess
ds-pwp-attribute-value-check-substrings: truebjenseSuccess
ds-pwp-attribute-value-check-substrings: truebjensenFailure: 19 (Constraint Violation)
ds-pwp-attribute-value-check-substrings: truebjensensFailure: 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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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
AttributeDescription

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 AttributeOverrides This Server Policy Property
pwdAllowUserChangeallow-user-password-changes
pwdMustChangeforce-change-on-reset
pwdGraceAuthNLimitgrace-login-count
pwdLockoutDurationlockout-duration
pwdMaxFailurelockout-failure-count
pwdFailureCountIntervallockout-failure-expiration-interval
pwdMaxAgemax-password-age
pwdMinAgemin-password-age
pwdAttributepassword-attribute
pwdSafeModifypassword-change-requires-current-password
pwdExpireWarningpassword-expiration-warning-interval
pwdInHistorypassword-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

Read a different version of :