Specialized password policies in DSEE

Anyone who has worked with the Netscape /Iplanet /Sun /Redhat /Oracle family of LDAP directory servers knows you can set a global password policy for all user entries on the directory (you really can). What they might not realize is that it is possible to set a specialized password policy (i.e. a “targeted password policy”) that can be discretely applied to just one or more entries.


Everything that follows applies to the latest Oracle DSEE product. Important details will differ in other products, like 389 Directory.

Start by reviewing the documentation (link is to the latest Oracle DSEE 11gR1 release).

This Worksheet is a very helpful tool for recording the details of your password policy design.

Here is how to check the settings for the global password policy on a DSEE instance:

dsconf get-server-prop -h localhost -v -i | grep ^pwd-

(see Managing the Default Password Policy)

Just some quick notes:

Here is what a specialized password policy entry looks like (this example is actually from the Sun Directory Server 5.2 Administration Guide):

dn: cn=TempPwdPolicy,dc=example,dc=com
objectClass: top
objectClass: passwordPolicy
objectClass: LDAPsubentry
cn: TempPwdPolicy
passwordChange: on
passwordMustChange: on
passwordCheckSyntax: on
passwordExp: on
passwordMinLength: 6
passwordMaxAge: 8640000
passwordMinAge: 0
passwordWarning: 259200
passwordInHistory: 6
passwordLockout: on
passwordMaxFailure: 3
passwordUnlock: on
passwordLockoutDuration: 3600
passwordResetFailureCount: 600
passwordRootdnMayBypassModsChecks: on

By default DSEE 6+ (including ODSEE 11g) directories are created in “DS5 Compatibility Mode” for password policy purposes. This is to insure interoperability with older directory servers. As a result, if you use the above code to create a policy on a post version 5.2 DSEE, it will add the new attribute names and values appropriate to the later version. Thus:

dn: cn=TempPwdPolicy,dc=example,dc=com
objectClass: top
objectClass: ldapsubentry
objectClass: passwordpolicy
objectClass: pwdPolicy
objectClass: sunPwdPolicy
cn: TempPwdPolicy
passwordChange: on
passwordCheckSyntax: on
passwordExp: on
passwordInHistory: 6
passwordLockoutDuration: 3600
passwordMaxAge: 8640000
passwordMaxFailure: 3
passwordMinAge: 0
passwordMinLength: 6
passwordResetFailureCount: 600
passwordRootdnMayBypassModsChecks: on
passwordUnlock: on
passwordWarning: 259200
pwdAllowUserChange: TRUE
pwdCheckQuality: 2
pwdExpireWarning: 259200
pwdFailureCountInterval: 600
pwdInHistory: 6
pwdMaxAge: 8640000
pwdMaxFailure: 3
pwdMinAge: 0
pwdMinLength: 6

This can be a real pain, since it requires the same change to be made in more than one place (for example, for password expiration times).

Here’s a purely post 5.2 DSEE (i.e. DSEE 6+) version of the same policy:

dn: cn=TempPwdPolicy,dc=example,dc=com
objectClass: top
objectClass: pwdPolicy
objectClass: sunPwdPolicy
objectClass: LDAPsubentry
cn: TempPwdPolicy
pwdAttribute: userPassword
pwdAllowUserChange: TRUE
pwdCheckQuality: 2
pwdLockout: TRUE
pwdLockoutDuration: 3600
pwdMaxFailure: 3
pwdMustChange: TRUE
pwdExpireWarning: 259200
pwdFailureCountInterval: 600
pwdInHistory: 6
pwdMaxAge: 8640000
pwdMaxFailure: 3
pwdMinAge: 0
pwdMinLength: 6
passwordRootdnMayBypassModsChecks: on

(note that pwdAttribute is required to create a post DS 5.2 password policy)

Loading this will still result in both old and new attribute types and values being added so long as compatibility mode is turned on.

This is how you would search for a specialized password policy (or any other “special” object of the “ldapsubentry” class):

ldapsearch -x -h localhost -D "cn=directory manager" -W 
-b "dc=example,dc=com" -s sub "(objectclass=ldapsubentry)"

(Note: Searching for “(objectclass=passwordpolicy)” will yield nothing — I don’t know why)

Most LDAP tree editors will not display ldapsubentry objects automatically. They need to be searched for explicitly because they are system/operational in nature. Apache Directory Studio will show them if you perform a “Quick” or regular search for “(objectclass=ldapsubentry)”.

There are a couple of ways to make a specialized policy apply to a given user. The “brute force” (or “blunt instrument”) method is to add an attribute and value to each entry you want it to apply to:

pwdPolicySubentry: cn=TempPwdPolicy,dc=example,dc=com

In Sun directories prior to DSEE 6, you’d use this:

passwordPolicySubentry: cn=TempPwdPolicy,dc=example,dc=com

Because this is a system attribute, some LDAP editors (like Apache Directory Studio) will not be able to add it. Use the command line ldapmodify utility instead.

You can search for all entries that have a password policy assignment with the following:

ldapsearch -x -h localhost -D "cn=directory manager" -W -b 
"dc=example,dc=com" -s sub "(pwdPolicySubentry=*)" pwdPolicySubentry

(note you’d need to substitute “passwordPolicySubentry” when querying a pre-DSEE 6 directory server)

This will return the dn of each entry with a password policy, as well as the dn of the password policy assigned to each. Again, as this is a system attribute you need to explicitly ask for it when performing a search.

That’s all easy enough, but could get tedious once you get up over a few entries.

Another way to do this is by employing CoS (Class of Service) and filtered roles to apply the policy to a class of entries. An important caveat to using CoS for something like this is that it always involves a performance penalty that can become significant depending on the number of affected entries. As a result I’ve decided to avoid using it in my own implementations, and to instead rely on batch update processes whose impact on the system can be controlled more closely.