Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading Local Group Policy / Active Directory Settings

I'm writing a C# program that will enforce password complexity in accordance with the Windows Group Policy setting "Password must meet complexity requirements". Specifically, if that policy is set to Enabled either on the local machine (if it's not part of a domain) or by the Domain Security Policy (for domain members), then my software needs to enforce a complex password for its own internal security.

The issue is that I can't figure out how to read that GPO setting. Google searches have indicated that I can read GPO settings with one of these two APIs: the System.DirectoryServices library in .NET Framework, and Windows Management Instrumentation (WMI), but I haven't had any success so far.

Any insights would be helpful.

like image 631
ShootTheCore Avatar asked Sep 30 '09 23:09

ShootTheCore


1 Answers

There doesn't appear to be a documented API for this task, managed or otherwise.

Managed Attempt

I tried the managed route using the System.Management assembly:

        ConnectionOptions options = new ConnectionOptions();
        ManagementScope scope = new ManagementScope(@"\\.\root\RSOP\Computer", options);

        ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, new ObjectQuery("SELECT * FROM RSOP_SecuritySettingBoolean"));
        foreach(ManagementObject o in searcher.Get())
        {
            Console.WriteLine("Key Name: {0}", o["KeyName"]);
            Console.WriteLine("Precedence: {0}", o["Precedence"]);
            Console.WriteLine("Setting: {0}", o["Setting"]);
        }

This however will not return results. It doesn't appear to be a permission issue as providing a username/password pair to ConnectionOptions results in an exception telling you that you can not specify a username when connecting locally.

Unmanaged Attempt

I looked at NetUserModalsGet. While this will return some information on password settings:

typedef struct _USER_MODALS_INFO_0 {
  DWORD usrmod0_min_passwd_len;
  DWORD usrmod0_max_passwd_age;
  DWORD usrmod0_min_passwd_age;
  DWORD usrmod0_force_logoff;
  DWORD usrmod0_password_hist_len;
} USER_MODALS_INFO_0, *PUSER_MODALS_INFO_0, *LPUSER_MODALS_INFO_0;

..it will not let tell if the Password Complexity policy is enabled.

Tool Output Scraping 'Success'

So I resorted to parsing secedit.exe output.

    public static bool PasswordComplexityPolicy()
    {
        var tempFile = Path.GetTempFileName();

        Process p = new Process();
        p.StartInfo.FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\system32\secedit.exe");
        p.StartInfo.Arguments = String.Format(@"/export /cfg ""{0}"" /quiet", tempFile);
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.UseShellExecute = false;
        p.Start();
        p.WaitForExit();

        var file = IniFile.Load(tempFile);

        IniSection systemAccess = null;
        var passwordComplexityString = "";
        var passwordComplexity = 0;

        return file.Sections.TryGetValue("System Access", out systemAccess)
            && systemAccess.TryGetValue("PasswordComplexity", out passwordComplexityString)
            && Int32.TryParse(passwordComplexityString, out passwordComplexity)
            && passwordComplexity == 1;
    }

Full code here: http://gist.github.com/421802

like image 76
Joseph Kingry Avatar answered Sep 22 '22 20:09

Joseph Kingry