Implementing an OpenLDAP password policy

In this guide, we will learn how to implement OpenLDAP password policies. In OpenLDAP, the password policy is by using Password Policy (ppolicy) Overlay. The ppolicy overlay provides multiple password control mechanisms, including:

  • Password age-minimum and maximum age
  • Password quality
  • Automatic account lockout
  • Password reuse and replication control
  • Account timeout
  • Force password reset
  • Acceptable password content
  • Grace logins allow expired passwords for a specific period of time after the expiration date.

Read more about policy man slapo-ppolicy.

Implementing an OpenLDAP password policy

Load password policy module

In order to implement an LDAP password policy, you need to make sure ppolicy.la The module has been loaded into the LDAP database. To list loaded modules, run the command;

slapcat -n 0 | grep -i module

In our current LDAP setup, there is no password policy module, ppolicy.la, Already loaded. See the output of the command above;

dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/libexec/openldap
olcModuleLoad: {0}back_mdb.la
olcModuleLoad: {1}memberof.la
olcModuleLoad: {2}refint.la
structuralObjectClass: olcModuleList
olcAttributeTypes: {15}( 1.3.6.1.4.1.4754.1.99.1 NAME 'pwdCheckModule' DESC 
 'Loadable module that instantiates "check_password() function' EQUALITY cas
 op AUXILIARY MAY pwdCheckModule )

So to load the module, you can simply create an LDIF file as shown below to define how to add the password policy module to slapd.

Please note that in our setup the module is under the path, /usr/libexec/openldap Such as olcModulePath Attributes.

vi load-ppolicy-mod.ldif
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la

Load the module into the LDAP database.

ldapadd -Y EXTERNAL -H ldapi:/// -f load-ppolicy-mod.ldif

After loading the module, if you list the extended module again, you should get output similar to the following (the specific situation may be different);

slapcat -n 0 | grep -i module
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/libexec/openldap
olcModuleLoad: {0}back_mdb.la
olcModuleLoad: {1}memberof.la
olcModuleLoad: {2}refint.la
olcModuleLoad: {3}ppolicy.la
structuralObjectClass: olcModuleList

Create password policy OU container

Create an LDAP OU container that will be used to store the default password policy.

vi pwpolicy-ou.ldif
dn: ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com
objectClass: organizationalUnit
objectClass: top
ou: pwpolicy
ldapadd -Y EXTERNAL -H ldapi:/// -f pwpolicy-ou.ldif

Create OpenLDAP password policy to override DN

After loading the policy module into the slapd database, continue to add the LDAP password policy cover DN.

Add a password policy overlay to your respective LDAP database backend (mdb in this setting).

ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b  cn=config olcDatabase | grep mdb

See the highlighted line in the output below;

dn: olcDatabase={1}mdb,cn=config
olcDatabase: {1}mdb
dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config

Create an LDIF file with the following to add the policy Overlay DN and configuration options to slapd. Replace the domain components accordingly.

vi pwpolicyoverlay.ldif
dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com
olcPPolicyHashCleartext: TRUE

Read above to learn more about configuration options applied to the policy overlay man slapo-ppolicy.

Update the database.

ldapadd -Y EXTERNAL -H ldapi:/// -f pwpolicyoverlay.ldif

Create OpenLDAP password policy

You can now create an LDAP password policy based on the default password policy ou created above, cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com.

of policy Coverage depends pwd policy Object classes, so you can use any of the properties described in the Object Class Properties section when defining a policy. man slapo-ppolicy.

vi ldap-pwpolicies.ldif
dn: cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com
objectClass: person
objectClass: pwdPolicyChecker
objectClass: pwdPolicy
cn: pwpolicy
sn: pwpolicy
pwdAttribute: userPassword
pwdMinAge: 0
pwdMaxAge: 5184000
pwdInHistory: 5
pwdCheckQuality: 2
pwdMinLength: 12
pwdExpireWarning: 432000
pwdGraceAuthNLimit: 5
pwdLockout: TRUE
pwdLockoutDuration: 0
pwdMaxFailure: 3
pwdFailureCountInterval: 0
pwdReset: TRUE
pwdMustChange: TRUE
pwdAllowUserChange: TRUE
pwdSafeModify: FALSE

For a detailed description of the above password attributes, please consult, man slapo-ppolicy. For a description of the object classes used, see, Object classes and attributes.

Update the password policy on slapd.

ldapadd -Y EXTERNAL -H ldapi:/// -f ldap-pwpolicies.ldif

Test password policy

To test the effectiveness of the implemented OpenLDAP password policy, we will try to change the password of one of the existing OpenLDAP users in the environment.

Some of the checks we implemented above include:

  • Password history: Store 5 previously used passwords in the database to avoid reuse.
  • pwdCheckQuality: Set to 2. The server will check the syntax of the password, and if the server cannot check the syntax, it will return an error and reject the password.
  • pwdMinLength: Set the minimum acceptable number of characters in the password to 12.

Try to set a simple password;

ldappasswd -H ldapi:/// -Y EXTERNAL -S "uid=june,ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com"
New password: password
Re-enter new password: password
...
Result: Constraint violation (19)
Additional info: Password fails quality checking policy

Reuse existing passwords;

ldappasswd -H ldapi:/// -Y EXTERNAL -S "uid=june,ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com"
New password: password1234
Re-enter new password: password1234
...
Result: Constraint violation (19)
Additional info: Password is not being changed from existing value

One thing I noticed in my test to test whether the user will be prompted to reset their password when they first log in, is that despite the password being set, pwdMustChange: TRUE Attribute unless you add it, pwdReset: TRUE On user input, this will not work.

So if you want to prompt the user to reset their password when they first log in, just edit the user entry and add pwdReset: true.

For example, if I want to prompt users in my LDAP database to reset their passwords in June, I just need to edit and update their entries as shown below;

vim mod-june.ldif
dn: uid=june,ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com
changetype: modify
add: pwdReset
pwdReset: TRUE
ldapmodify -Y EXTERNAL -H ldapi:/// -f mod-june.ldif

To test this now, just try to log in to the system as a June user.

If using SSSD for authentication, please clear the cache;

systemctl stop sssd;rm -rf /var/lib/sss/db/*;systemctl restart sssd

log-in name;

ssh -l june localhost
[email protected]'s password: current-password Password expired. Change your password now. Creating directory '/home/june'. Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-20-generic x86_64)  * Documentation:  https://help.ubuntu.com  * Management:     https://landscape.canonical.com  * Support:        https://ubuntu.com/advantage  * Canonical Livepatch is available for installation.    - Reduce system reboots and improve kernel security. Activate at:      https://ubuntu.com/livepatch Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Sun Jan  5 11:43:09 2020 from ::1 WARNING: Your password has expired. You must change your password now and login again! Current Password: current-pass New password: New-pass-that-meets-policies-set Retype new password: New-pass-that-meets-policies-set passwd: password updated successfully

Learn more about OpenLDAP password policies Administrator’s Guide: Overlays.

Implementing a password complexity policy

Well, as you can see, you can even use a simple password, as long as it complies with some of the policies set above, it can be easily cracked.

So how do we implement a password complexity check strategy on OpenLDAP? You need to install an additional LDAP module for password complexity checking.

In this demo we will use pqChecker It enables you to define the following functions of the password;

  • Number of required uppercase characters.
  • Required lowercase characters.
  • Required number of special characters (non-alphabetic characters).
  • The required number of digits (0-9).
  • Forbidden characters

Install pqChecker on CentOS 8

Since we have set up the OpenLDAP server on CentOS 8 system, we installed the pqchecker module on the same server.

prerequisites

Download the OpenLDAP source tarball and unzip it (if not already done), and make sure the necessary build tools are installed. Follow the link to the OpenLDAP server settings provided above.

Next, install JAVA sdk. In this demo, we use Java 11.

dnf install java-11-openjdk-devel

Clone pqchecker github repository

git clone https://bitbucket.org/ameddeb/pqchecker.git

Install pqchecker

Navigate to the OpenLDAP source directory and build dependencies.

cd openldap-2.4.48
./configure
make depend

Next, navigate to the cloned pqchecker directory and install it as shown below;

cd ~/pqchecker
autoreconf -f -i
./configure LDAPSRC=/root/openldap-2.4.48 JAVAHOME=/usr/lib/jvm/java-11-openjdk-11.0.5.10-0.el8_0.x86_64 PARAMDIR=/etc/openldap/pqchecker libdir=/usr/libexec/openldap

Replace the value of a variable, LDAPSRC, JAVAHOME, PARAMDIR with libdir Correspondingly.

make install /etc/openldap/pqchecker

pqchecker is now installed on /usr/libexec/openldap/pqchecker.so.

After the installation is complete, adjust the ownership of the pqchecker directory.

chown -R ldap:ldap /etc/openldap/pqchecker/

Update the password policy OU container created above, cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=comTo load the pqchecker module.

cd ~
vim mod-ppolicy.ldif
dn: cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com
changetype: modify
add: pwdCheckModule
pwdCheckModule: pqchecker.so
ldapadd -Y EXTERNAL -H ldapi:/// -f mod-ppolicy.ldif

Configure the pqChecker module

You can use the following commands to control the password complexity settings provided by pqChecker: /etc/openldap/pqchecker/pqparams.dat Configuration file created automatically when pqchecker is installed.

The following complexity checks are enabled by default;

less /etc/openldap/pqchecker/pqparams.dat
# Data format: 0|[email protected])..
# Or         : 1|[email protected])..
#
# 1st character is the modified passwords broadcast flag. 1 -> Broadcast, 0 -> Don't broadcast
# 2nd character is a separator
# U: Uppercase, L: Lowercase, D: Digit, S: Special characters -> from 3rd to 10th character.
# From the 11th character begins the list of forbidden characters
# Default: No broadcast, 1 Uppercase, 1 Lowercase, 1 digit, 1 Special and no forbidden characters
0|01010101

This basically means a password set based on the following format: UULLDDSS, which should contain at least one uppercase letter, one lowercase letter, one digit, one special character without forbidden characters, (01010101).

Well, another limitation of this enforcement is that it ignores the minimum password length policy set above, pwdMinLength: 12.

So for my minimum password length strategy to work, I had to try using pqChecker’s password format so that the total length of the password allowed me to contain at least 12 characters.

The format used here is:

0|04040202

This means that the password should contain at least;

  • Four uppercase characters
  • Four lowercase characters
  • Double digit
  • Two special characters.

Test password complexity

As an LDAP user on the LDAP-connected system, try resetting the password. In this demo, we use Ubuntu 18.04 as the test client.

Use old password;

[email protected]:~$ passwd
Current Password: password 
New password: [email protected]#nk19
Retype new password: [email protected]#nk19
Password change failed. Server message: Password is in history of old passwords
passwd: Authentication token is no longer valid; new one required
passwd: password unchanged

Use a new password that meets the defined complexity, ZX#[email protected].

[email protected]:~$ passwd
Current Password: 
New password: 
Retype new password: 
passwd: password updated successfully

Well, if you know of other tips for implementing OpenLDAP password complexity checking, feel free to remove the suggestions in the suggestions.

This marks the end of our guide on how to implement OpenLDAP password policies.

Sidebar