Determine AD password policy programmatically
I have been using the System.DirectoryService
(ADSI) classes and methods to create and change users in an Active Directory.
Recently we added a feature to allow users to set their own password through the system. However, using the SetPassword
method throws an exception when the password is not accepted by the Password Polic开发者_开发技巧y set.
userEntry.Invoke("SetPassword", new object[] {password});
My question is: How do I check to see if a password lives up to the password policy, before attempting to use the SetPassword-method?
I read in this post that you can get the Password Policy-settings from the root domain node, but where can I read more about what each attribute means? For instance, which characters are required to fullfill the "Complexity" policy?
Once I know this, I can implement my own password check-method, but as this is an error-prone approach, I would rather use a built-in check and give the user appropriate info on what is wrong with their password.
I am working on a similar project at my work. We are rolling a forgot password application. I ended up just doing an Invoke("SetPassword", "[randomString]")
and saved the random string for the Invoke("ChangePassword","[randomString]","[user supplied pw]")
. The result of the ChangePassword
was returned to the user.
SetPassword does not check for password complexity or history rules. It is the same as right clicking a user in AD and selecting "Reset Password." ChangePassword
however, does check for password history requirements.
The API function you want is NetValidatePasswordPolicy.
There are three modes it operates in:
NetValidateAuthentication
: if you are authenticating a user; so the function can check password expiration policies, bad login attempts, account lockouts, bad login attempts, etcNetValidatePasswordChange
: if the user is changing their password; so the function can check against lockout, or against the password policy
and the mode you want:
NetValidatePasswordReset
: you are an admin resetting a user's password; which only checks the password complexity.
I'll try transcoding from another language to C# on the fly; but you will have to P/Invoke it.
<summary>Check password during password reset.
The result from NetValidatePasswordReset, this member can be one of the following values.
NERR_Success The password passes the validation check.
NERR_PasswordTooShort Validation failed. The password does not meet policy requirements because it is too short.
NERR_PasswordTooLong Validation failed. The password does not meet policy requirements because it is too long.
NERR_PasswordNotComplexEnough Validation failed. The password does not meet policy requirements because it is not complex enough.
NERR_PasswordFilterError Validation failed. The password does not meet the requirements of the password filter DLL.
</summary>
UInt32 TestPasswordComplexity(String username, SecureString password)
{
//All code on stack overflow is in the public domain; no attribution
//is required.
const UInt32 NetValidatePasswordReset = 3;
NET_VALIDATE_PASSWORD_RESET_INPUT_ARG args = new NET_VALIDATE_PASSWORD_RESET_INPUT_ARG();
args.UserAccountName = Username; //some policies check that your password cannot contain your username
args.ClearPassword = SecureStringToString(password);
PNET_VALIDATE_OUTPUT_ARG res;
DWORD le = NetValidatePasswordPolicy(null, null, NetValidatePasswordReset, @args, {out}Pointer(res));
if (le <> NERR_Success)
throw new WindowsException(le); //
return res.ValidationStatus;
}
The complexity policy is that it must contain three out of five of these types:
- Upper case letters
- Lower case letters
- Digits
- Non-alphanumeric characters: ~!@#$%^&*_-+=`|(){}[]:;"'<>,.?/
- Unicode characters that are alphabetics but not uppercase or lowercase.
It also can't be the sAMAccountName or displayName (or parts of). You can read about it here. The other password policy rules are in adjacent documents.
You could try setting it and catch exceptions but from memory I don't think it tells you what's wrong with the password, just that it doesn't meet the requirements.
精彩评论