Password Settings Objects
Added in Samba version: 4.9
Password Settings Objects (PSOs) are an AD feature that's also known as Fine-Grained Password Policies (FGPP). In AD, the password settings control:
- Minimum password length and complexity requirements when a user changes their password.
- Password history length: prevents a user from re-using a previous password again.
- Minimum and maximum password age: how frequently the user can/must change their password.
- Account lockout: the threshold of unsuccessful login attempts before locking a user out of their account, and the duration they're locked out for.
Prior to supporting PSOs, Samba Administrators could only configure password settings for all users in the domain. E.g. if you wanted to enforce that system admins have longer, more-secure passwords, then every user had to conform to the same password requirements.
PSOs allow AD administrators to override the domain's password policy settings and configure finer-grain password-settings for specific users, or groups of users. For example, PSOs can force certain users to have longer password lengths, or relax the complexity constraints for other users, and so on. PSOs can be applied to groups or to individual users.
How to configure it
PSOs can be configured and applied to users/groups using the
samba-tool domain passwordsettings pso set of commands. Refer to
samba-tool domain passwordsettings pso --help for more detail. The PSO commands:
- Manage the PSOs themselves, i.e. configure the password settings using 'create' or 'set' sub-commands. There's also 'delete', 'list', and 'show' commands.
- Control what PSO applies to a particular user. Use the 'apply' and 'unapply' to link a PSO to a particular group or user.
Many different PSOs can apply to the same user (either directly, or via groups). When multiple PSOs apply to the same user, essentially the PSO with the lowest precedence takes effect. However, PSOs that apply directly to a user always trump PSOs inherited via group membership. To see what PSO takes effect for a given user, use
samba-tool domain passwordsettings pso show-user.
If no PSO applies to a user, then the domain password settings apply. You can view/modify these using
samba-tool domain passwordsettings show|set.
- Please use samba-tool to create the Password Settings Objects, rather than using a manual LDIF. The PSOs need to reside in the 'Password Settings Container', which samba-tool will sort out automatically. Any PSOs created elsewhere will be ignored.
- The Built-in groups are not included in the PSO calculation. Any PSOs applied to a built-in group will not take effect.
To create a PSO using the Windows GUI, open Active Directory Administrative Center, then navigate to System -> Password Settings Container, then clicking the 'New' button will bring up a wizard.
Known issues and limitations
There is currently (v4.9) a performance hit from configuring PSOs and applying them to users. This is something we will hopefully address in the future.
Calculating the PSO involves calculating the user's group memberships, which is a fairly expensive calculation. Even worse, we may need to lookup the msDS-ResultantPSO multiple times, so it may try to calculate the groups several times, just for one user authentication operation. Note that:
- If there are no PSO objects at all, there is no performance hit.
- We try to cache the msDS-ResultantPSO result, so we only work it out once per user-auth operation. However, we don't cache the result if there is no msDS-ResultantPSO (i.e. the domain defaults apply to the user). So that would be the worst case: where some PSOs exist in the domain, but they don't take effect for most users.
- If the PSO applies directly to a user (rather than a group), then the expensive group calculations are skipped. However, applying PSOs directly to users makes PSOs more of a pain to manage, compared with applying PSOs to groups.
There's also a really trivial bug (#13431) between Windows and Samba behaviour if the password-history-length changes from zero to a non-zero value.
Probably the most helpful command is
samba-tool domain passwordsettings pso show-user, which shows you the msDS-ResultantPSO for a user. Debug level 5 will also tell you the msDS-ResultantPSO, every time it's queried for a user.
It's sensible to give the PSOs descriptive names. Otherwise, it you have a lot of PSOs configured, it may get hard to track which group a user is inheriting a PSO from.
To check the PSO's settings actually take effect, it'd be simplest to create a temporary user for testing. Apply the PSO to the temp-user, then try changing the temp-user's password, or entering the wrong password repeatedly, etc, to verify the correct password restrictions and account lockout are applied. Remove the temporary user once you're happy the PSO settings are correct. The PSO should work exactly the same for any other user (i.e. as long as
samba-tool domain passwordsettings pso show-user shows that the PSO applies).
How to test it
The following tests the DSDB behaviour, i.e. it asserts that the msDS-ResultantPSO attribute is both constructed and applied correctly.
make test TESTS=ldap.passwordsettings
The following tests the samba-tool commands that configure PSOs.
make test TESTS=samba_tool.passwordsettings
You can run both tests with
make test TESTS=passwordsettings.
Note that there are also blackbox.password_settings tests that are unrelated to PSOs.
Where the code is located
The main PSO behaviour is controlled using a constructed attribute: msDS-ResultantPSO. This gets generated for user objects and its value is the DN of the PSO that applies to that user. So the logic that determines the correct PSO that applies to a user lives in operational.c, where the constructed attributes get generated.
If you grep the codebase for 'msDS-ResultantPSO', you should find all the places that try to use it. Basically wherever the code checked a password-setting attribute (e.g. like lockOutObservationWindow), we have to check if a PSO applies to that user, and if so then use the PSO attribute (which has a different name, i.e. msDS-LockoutObservationWindow) instead. samdb_result_effective_badPwdCount() is a good example of this.
get_pso_data_callback() is also notable, as it overrides the dsdb_user_pwd_settings struct's values (i.e. the domain password-settings) with the PSO's values. This struct gets used (as part of struct dsdb_control_password_change_status) in the password-hash module, to check password change operations.
- MS-ADTS documents how the msDS-ResultantPSO is determined (section 18.104.22.168.5.36).
- MS-SAMR documents how the msDS-ResultantPSO is used to determine the effective password setting that gets applied to a user, i.e. Effective-LockoutThreshold, Effective-MinimumPasswordLength, etc. This is documented in section 22.214.171.124 Password Settings Attributes for Originating Update Constraints, but these Effective-XYZ values get referenced in several other places throughout the document, e.g. when calculating userAccountControl.