0

I have searched tons of webs and tutorials but I couldn't find an answer to my problem.

I have set up OpenLDAP 2.4 on a OpenSUSE 12.3 machine with a password policy overlay. The client is a Linux Mint 17.1 machine with libnss-ldap and libpam-ldap packages installed. The client and server are configured to use TLS with self-signed certificates (the server works as a CA and signs its own certificate). Everything works fine until I add the attribute pwdReset: TRUE to a user.

My intention is to force the user to change his password at next login. However, after setting this attribute the user can no longer authenticate: if I try to 'su' (or login with) the user I get the error "Authentication Failure". Also, the syslog shows the following messages:

Mar 4 07:27:11 client-desktop nslcd[3198]: [90cde7] <authc="johndoe"> ldap_result() failed: Insufficient access: Operations are restricted to bind/unbind/abandon/StartTLS/modify password
Mar 4 07:27:11 client-desktop nslcd[3198]: [dcc233] <authc="johndoe"> cn=John Doe,ou=people,cd=domain,dc=com: lookup failed: Invalid credentials

This messages tell me that the user credentials are no longer valid, which is reasonable since I reset his password but the user is not prompted about the need to change his password or whatsoever. Addtionally, I want to prevent the use of openldap utils like ldappasswd as the clients are not experts. Therefore, I want them to keep on using the typical passwd command to change their own passwords. At least, this is possible when pwdReset is not set. Also, I can get this behaviour by setting the shadowLastChange attribute to 0, but I would like to do everything with password policies since I am also trying to enforce the use of passwords of at least 8 chars. By the way, this feature works perfectly fine.

This is an excerpt of my base DN so that you can check if I am missing something. Note that pwdReset is set to TRUE on the user and pwdMustChange variable is set to TRUE in the policy itself.

# John Doe, people, domain.com
dn: cn=John Doe,ou=people,dc=domain,dc=com
cn: John Doe
sn: Doe
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
uid: johndoe
uidNumber: 1003
gidNumber: 1000
homeDirectory: /home/johndoe
loginShell: /bin/bash
userPassword: e1NTSEF9VWFSMDVsSGNIWFMxcnJ5VzBtaWRkOHFmTDE1ai9RYlQ=
pwdReset: TRUE # This attribute only appears if I explicitly request it 

# policies, domain.com
dn: ou=policies,dc=domain,dc=com
objectClass: top
objectClass: organizationalUnit
ou: policies

(The following attributes belong in cn=default,ou=policies but for some reason they don't appear unless I write something here)

pwdInHistory: 3
pwdLockout: TRUE
pwdMaxFailure: 3
pwdLockoutDuration: 30
pwdMustChange: TRUE
pwdSafeModify: FALSE
pwdAllowUserChange: TRUE
pwdFailureCountInterval: 0
pwdGraceAuthNLimit: 0

And this is the configuration of my backend and the password policies:

# {1}hdb, config
dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=domain,dc=com
olcAccess: {0}to attrs=userPassword by self write by * auth
olcAccess: {1}to attrs=shadowLastChange by self write by * read
olcAccess: {2}to attrs=userPKCS12 by self read by * none
olcAccess: {3}to * by * read
olcRootDN: cn=admin,dc=domain,dc=com
olcRootPW: {SSHA}############## omited
olcDbCacheSize: 10000
olcDbCheckpoint: 1024 5
olcDbConfig: {0}set_cachesize 0 15000000 1
olcDbConfig: {1}set_lg_regionmax 262144
olcDbConfig: {2}set_lg_bsize 2097152
olcDbConfig: {3}set_flags DB_LOG_AUTOREMOVE
olcDbConfig: {4}set_lk_max_locks 30000
olcDbConfig: {5}set_lk_max_objects 30000
olcDbIDLcacheSize: 30000
olcDbIndex: objectclass eq
[...more indexes...]

# {0}ppolicy, {1}hdb, config
dn: olcOverlay={0}ppolicy,olcDatabase={1}hdb,cn=config
objectClass: top
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: {0}ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=domain,dc=com
olcPPolicyHashCleartext: TRUE

(The following two attributes belong also in {0}ppolicy)

olcPPolicyUseLockout: FALSE 
olcPPolicyForwardUpdates: FALSE

I hope someone can shed some light on this. Any help is extremely appreaciated!

Regards

Edit:

I have made some modifications to the default policy in order to gain insight into what was impeding the user authentication. I have realised that if pwdMustChange is set to TRUE and pwdReset is also set to TRUE (this one on the user entry), then user authentication fails with error 'su: Authentication failure'. However, if pwdReset is TRUE and pwdMustChange is FALSE, then I login as many times as I want with that user. I think that having two varibles for this is useless and counterintuitive. Instead a single variable should be used on user's entry only, whatever you want to call it either pwdReset or pwdMustChange.

rutex
  • 1
  • 2

1 Answers1

0

Policies on the LDAP server don't necessarily equate to policies within the OS. You seem to be picturing a framework where you set this overflay property and the OS becomes aware of the need for a password change, but as you can see that's not how it works.

To trigger a prompt within the operating system, an accounting module (typically PAM) has to notice the condition. OpenLDAP's password policy overlay is not a POSIX standard. Unlike what happens when you adjust the shadow properties of a user to set the policy, pam_unix has no awareness of these attributes that you're setting. The same cannot be said of the OpenLDAP server itself. This results in a user lockout because the user cannot authenticate to the Linux server, and lacks sufficient information about LDAP (as you yourself note) to work directly with the LDAP server to change their password.

If you're looking to trigger password change prompts within the OS, this is not the right tool for the job. I would personally recommend that you familiarize yourself with the relevant shadow attributes, store them in LDAP if they need to be centrally managed, and use those to trigger the behaviors you're looking for.

From the pam_unix(8) manpage:

The account component performs the task of establishing the status of the user's account and password based on the following shadow elements: expire, last_change, max_change, min_change, warn_change. In the case of the latter, it may offer advice to the user on changing their password or, through the PAM_AUTHTOKEN_REQD return, delay giving service to the user until they have established a new password. The entries listed above are documented in the shadow(5) manual page. Should the user's record not contain one or more of these entries, the corresponding shadow check is not performed.

Andrew B
  • 32,588
  • 12
  • 93
  • 131
  • Thank you very much for the comments. So, should I assume I won't be able to make it work on a Linux box? I am asking because it seems that some guys have managed to do so. See this [link](http://serverfault.com/questions/460143/linux-ubuntu-vs-centos-ldap-client-for-389-ds-password-policy) where it seems to work on CentOS but not on Ubuntu; or this other [link](http://www.andyloughran.co.uk/2007/10/19/howto-ppolicy-openldap/) where, at the end, the guy says "login now with your username ($user) and your old password. It will then log you in and ask you to change it." – rutex Mar 05 '15 at 06:22