Implement OpenLDAP Password Policies

0
242

In this guide, we are going to learn how to implement OpenLDAP password policies. In OpenLDAP, password policies are implemented through the use of Password Policy (ppolicy) Overlay. ppolicy overlay provides a variety of password control mechanisms including;

  • Password aging — both minimum and maximum ages
  • Password quality
  • Automatic account locking
  • Password reuse and duplication control
  • Account time-outs
  • Mandatory password resets
  • Acceptable password content
  • Grace logins to allow the use of expired passwords for a specific time period after the expiry date.

Read more about ppolicy overlay on man slapo-ppolicy.

Implement OpenLDAP Password Policies

Load Password Policy Module

In order to implement LDAP password policies, you need to ensure that the, ppolicy.la module is loaded onto LDAP database. To list loaded modules, run the command;

slapcat -n 0 | grep -i module

In our current LDAP setup, no password policy module, ppolicy.la, is 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 )

Therefore, 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.

Note that in our setup, the modules are located under the path, /usr/libexec/openldap as defined by the olcModulePath attribute.

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

Load the module in to LDAP database.

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

After loading the module, if you list the slapd modules again, you should get an output similar to the below (It might be different for your case);

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 Policies OU Container

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

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 Overlay DN

Once you have loaded the ppolicy module into slapd database, proceed to add the LDAP password policy Overlay DN.

Add the password policy overlay into your respective LDAP database backend, which in this setup is mdb.

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 content below for adding the ppolicy Overlay DN along with the configuration options into 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 more about the configuration options applied to the ppolicy overlay above on man slapo-ppolicy.

Update the database.

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

Create OpenLDAP Password Policies

You are now ready to create your LDAP password policies under your default password policies ou created above, cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com.

The ppolicy overlay depends on the pwdPolicy object class and thus when defining the policies, you can use any of the attributes described under the ObjectClass attributes section of 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 good explanation of the password attributes used above, consult, man slapo-ppolicy. For a description of object classes used consult, Object Classes and Attributes.

Update the Password policies on the slapd.

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

Testing Password Policies

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

Some of the checks we implemented above include;

  • pwdInHistory: stores 5 previously used passwords in the database to avoid re-use.
  • pwdCheckQuality: Set to value to 2. The server will check the syntax of the password and if the server is unable to check the syntax it will return an error refusing the password.
  • pwdMinLength: Sets the minimum number of characters that will be accepted in a password to 12.

Try setting 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

Re-using the existing password;

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 that i noticed while testing on whether the user will be prompted to reset their password on first time login is that, despite having set the, pwdMustChange: TRUE attribute, unless you add the attribute, pwdReset: TRUE on the user entry, this will not work.

So if you want the user to be prompted to reset their passwords on first time login, simply edit the user entry and add the pwdReset: TRUE.

For example, if I want the user, june, in my LDAP db to be prompted to reset the password, I would simply edit and update its entry as follows;

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

Now, to test this, simply try to login to a system as user june.

If using SSSD for authentication, clear the cache;

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

The login;

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

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

Enforcing Password Complexity Policy

Well, as you can see, you can even use a simple password that can easily be broken as long it meets some of the policies set above.

So how can we enforce a password complexity checks policy on OpenLDAP? You need to install extra LDAP modules for password complexity checks.

In this demo, we are going to use the pqChecker which enables you to define the following features of a password;

  • Number of required uppercase characters.
  • Number of required lowercase characters.
  • Number of required special characters (non-alphabetical characters).
  • Number of required digits (0-9).
  • Forbidden characters

Install pqChecker on CentOS 8

Since we have setup our OpenLDAP server on a CentOS 8 system, we install the pqchecker module on the same server.

Prerequisites

Download OpenLDAP source tarball and extract it, (if not already done) and ensure that you have the required build tools in place. Follow the OpenLDAP server setup link provided above for how to do this.

Next, install JAVA sdk. We use Java 11 in this demo.

dnf install java-11-openjdk-devel

Clone pqchecker github repository

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

Install pqchecker

Navigate to OpenLDAP source directory and build the dependencies.

cd openldap-2.4.48
./configure
make depend

Next, navigate to cloned pqchecker directory and install it as follows;

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 values of the variables, LDAPSRC, JAVAHOME, PARAMDIR and libdir accordingly.

make install /etc/openldap/pqchecker

The pqchecker is now installed under /usr/libexec/openldap/pqchecker.so.

Once the installation completes, 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=com, to 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

Configuring pqChecker Module

The password complexity settings provided by pqChecker can be controlled using the /etc/openldap/pqchecker/pqparams.dat configuration file that is created automatically while installing pqchecker.

By default, the following complexity checks are enabled;

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 the password set, based on the format: UULLDDSS, should contain at least one upper case character, one lower case character, one digit, one special character with no forbidden character, (01010101).

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

So in order for my minimum password length policy to play ball, i had to play around with the password format of the pqChecker such that the total length of the password would get me at least 12 characters.

The format used here is:

0|04040202

Which means the password should contain at least;

  • Four uppercase characters
  • Four lowercase characters
  • Two digits
  • Two special characters.

Testing Password Complexity

As an LDAP user on an LDAP connected system, try to reset your password. In this demo, we are using Ubuntu 18.04 as the test client.

Using an 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

Using new password that obeys the complexity defined, ZX#[email protected].

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

Well, if you are aware of other tricks of implementing OpenLDAP password complexity checks, feel free to drop the suggestions in the comments.

That marks the end of our guide on how to implement OpenLDAP Password Policies.

Related Tutorials

Configure SSSD for OpenLDAP Authentication on CentOS 8

How to Create OpenLDAP Member Groups

Configure SSSD for OpenLDAP Client Authentication on Debian 10/9

How to Configure SUDO via OpenLDAP Server

LEAVE A REPLY

Please enter your comment!
Please enter your name here