简体   繁体   中英

Validate Windows password policy programmatically?

I have an application for bulk creating users (atypical I know, but not my decision) and currently, the validation for the password is just done using regular expressions. But the specific requirements can change depending on the PC's settings, right? So is there a way to test a given string against the PC's password policy in C#? I want to be able to do something like:

bool isPasswordGood = TestPasswordComplexity("notAgoodPassword");

This will depend on the security policy set up in Windows. That is typically set up using the GUI for setting security policies, but you can actually export the settings from command line as follows:

secedit.exe /export /cfg C:\temp\MySecurityPolicy.inf

Note: You may need to run command prompt as an admin for this to be permitted (right click the command prompt icon and select Run as administrator ).

That should save your settings in a text file (here, MySecurityPolicy.inf ). The first part of this file should look like this:

[Unicode]
Unicode=yes
[System Access]
MinimumPasswordAge = 0
MaximumPasswordAge = 365
MinimumPasswordLength = 12
PasswordComplexity = 0
PasswordHistorySize = 20
LockoutBadCount = 20
ResetLockoutCount = 10
LockoutDuration = 10
RequireLogonToChangePassword = 0
ForceLogoffWhenHourExpire = 1
NewAdministratorName = "LocalAdmin"
NewGuestName = "LocalGuest"
ClearTextPassword = 0
(...)

In particular I would imagine that lines 6 & 7, MinimumPasswordLength and PasswordComplexity will be of interest - There is some documentation about this available here

Once you understand how this works, you should be able to create a simple script or program to read from such a config file, and use the info from it to inform your password validation method. Perhaps it might even suffice to only read lines 6 & 7?

I realize this might not be as good as being able to look up the policy settings directly from C#, but it will at least give you an option: Now whenever you need to check requirements, run a script that exports the settings to a known file, and re-evaluate it from your application.

If you can run the export procedure from your app too (assuming the elevated privileges requirements don't cause trouble), then you should be able to automate all of this. Otherwise, you might have to export the policy file manually, and store it in a location your app can read from.

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, etc
  • NetValidatePasswordChange : 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.

/*
    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.
*/

UInt32 TestPasswordComplexity(String username, SecureString password)
{
   const UInt32 NetValidatePasswordReset = 3;

   NET_VALIDATE_PASSWORD_RESET_INPUT_ARG args = new NET_VALIDATE_PASSWORD_RESET_INPUT_ARG();
   args.UserAccountName = "Kjartan"; //some policies check that your password cannot contain your username

   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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM