OpenLDAP, Samba and password aging

I wrote my own OpenLDAP overlay called shadowlastchange to update the shadowLastChange attribute whenever an EXOP password change occurs. It is activated in slapd.conf:

moduleload smbk5pwd
moduleload shadowlastchange
...

database bdb
...
overlay smbk5pwd
overlay shadowlastchange

I have configured smb.conf to change passwords via EXOP:

ldap passwd sync = Only

Then, for each account, set shadowMax to the number of days a password is valid. The OpenLDAP modules take care of the rest!


As a stop-gap I created script for Samba that will update the shadowLastChange on password change:

#!/bin/sh
# script to update shadowLastChange when samba updates passwords
# it's not needed when using 'passwd', it does update the field,
# even if pam_ldap is using LDAP Extented Operation to change password

LDAP_MODIFY="/usr/bin/ldapmodify"
LDAP_SEARCH="/usr/bin/ldapsearch"
LDAP_USER="uid=shadow-update,ou=Services,dc=example,dc=com"
LDAP_PASSWORD="change-me"
LDAP_HOST="localhost"

# get date
SLC=$((`date '+%s'` / 24 / 3600))

# get user login name
user=$1

# find user's DN
dn=$($LDAP_SEARCH -x -h $LDAP_HOST -LLL -b dc=example,dc=com "(uid=$user)" dn)
dn=${dn#dn:}

# check if DN is not base64 encoded
if [ "${dn:0:1}" = ":" ]; then
        # update password change date
        echo "dn:$dn
changetype: modify
replace: shadowLastChange
shadowLastChange: $SLC" | cat | $LDAP_MODIFY -x -h "$LDAP_HOST" \
 -D "$LDAP_USER" -w "$LDAP_PASSWORD" > /dev/null 2>&1
else
        # update password change date
        echo "dn: $dn
changetype: modify
replace: shadowLastChange
shadowLastChange: $SLC" | cat | $LDAP_MODIFY -x -h "$LDAP_HOST" \
 -D "$LDAP_USER" -w "$LDAP_PASSWORD" > /dev/null 2>&1
fi

err=$?

if [ ! $err -eq 0 ]; then
   echo "error: can't update shadowLastChange: $err"
   echo "`date`: shadow.sh: can't update shadowLastChange: $err"\
       >> /var/log/shadow-update.log
   exit;
fi

echo OK

In Samba config it needs unix password sync set to yes, passwd chat set to *OK* and passwd program to above script with "%u" as param.

An account specified in LDAP_USER needs to be created in LDAP and given permissions to read on uid of all Samba users and the right to write shadowLastChange.


(work in progress, I'll add details later)

Good news everyone! I got the whole thing working, more or less..., in a testing environment...:

  1. Password policy (both quality- and time-wise) is enforced on OpenLDAP level (thanks to ppolicy, not24get and passwdqc)
  2. Passwords are synchronised between Samba and POSIX in both ways (thanks to smbk5pwd). Note: Quality checking with Samba and ppolicy is non obvious: the password check script (pwqcheck -1 from passwdqc) needs to perform the same checks the LDAP does or the user will get a Permission Denied instead of "Too easy password, try different".
  3. Both PAM and Samba warn the user that the password will soon expire.
  4. User directories are created using pam_mkhomedir
  5. GOsa² implementation of RFC2307bis (and associated schema) inserts uid to group entries, so applications expecting either NIS (most of "UNIXy" stuff) or RFC2307bis schema (most of "designed for AD" applications) work just fine.

The only problem is that disabling an account requires use of CLI tools (or writing GOsa postmodify script) or the account won't be locked at LDAP level, just for PAM and Samba. The password expiration will still be enforced, so it's not a big problem.