Search code examples
c#wmipassword-policywindows-users

Check MaxPasswordAge in Windows with local C# application


I am having the worst time trying to find documentation of this on the internet. Essentially I want to know that Secpol MaXPWAge is set to 90 or less and have it display in a textbox (let's call it textbox1 for ease) I have searched WMI solution, registry, GPEDIT in auditor and have found nothing. I did find this, but honestly, I have no clue how to use the same code to check the Max Password Age instead of complexity requirements. PLEASE, can someone show me what I should be doing here? C# is not my primary language.

https://gist.github.com/jkingry/421802

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Console.Write(PasswordComplexityPolicy());
    }

    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;
    }

    class IniFile
    {
        public static IniFile Load(string filename)
        {
            var result = new IniFile();
            result.Sections = new Dictionary<string, IniSection>();
            var section = new IniSection(String.Empty);
            result.Sections.Add(section.Name, section);

            foreach (var line in File.ReadAllLines(filename))
            {
                var trimedLine = line.Trim();
                switch (line[0])
                {
                    case ';':
                        continue;
                    case '[':
                        section = new IniSection(trimedLine.Substring(1, trimedLine.Length - 2));
                        result.Sections.Add(section.Name, section);
                        break;
                    default:
                        var parts = trimedLine.Split('=');
                        if(parts.Length > 1)
                        {
                            section.Add(parts[0].Trim(), parts[1].Trim());
                        }
                        break;
                }                    
            }

            return result;
        }

        public IDictionary<string, IniSection> Sections { get; private set; }
    }

    class IniSection : Dictionary<string, string>
    {
        public IniSection(string name) : base(StringComparer.OrdinalIgnoreCase)
        {
            this.Name = name;
        }

        public string Name { get; private set; }
    }
}

Solution

  • This is kind of a cheat, but it works if you're only looking for that one thing. Basically it starts a new process and runs net accounts, then scapes the Maximum password age field from the output. Try it out, but you might have to run it as an administrator:

    var process = new Process
    {
        StartInfo = new ProcessStartInfo()
        {
            FileName = "net",
            Arguments = "accounts",
            UseShellExecute = false,
            RedirectStandardOutput = true,
            CreateNoWindow = true
        }
    };
    
    process.Start();
    string text = "";
    while (!process.StandardOutput.EndOfStream)
    {
        text = process.StandardOutput.ReadLine();
        if (text != null && text.StartsWith("Maximum password age (days):"))
            break;
    }
    if (text == null || !text.StartsWith("Maximum password age (days):"))
        return;
    text = text.Replace("Maximum password age (days):", "").Trim();
    
    textBox1.Text = text;