窗口有五个与密码安全相关的策略设置:

>强制密码历史记录
>最大密码年龄
>最小密码年龄
>最小密码长度
>密码必须满足复杂性要求
>使用可逆加密存储密码

我知道如何使用NetUserModalsGet读取most of these items.但它不支持检查密码复杂性要求是否启用:

>强制密码历史记录:usrmod0_password_hist_len
>最大密码年龄:usrmod0_max_passwd_age
>最小密码年龄:usrmod0_min_passwd_age
>最小密码长度:usrmod0_min_passwd_len
密码必须符合复杂性要求:?
>使用可逆加密存储密码:

我也知道,WMI的RSOP(“结果集策略”)不合适,as it only works on a domain.我肯定不会去crawling through an undocumented binary blob(即我想要支持的方式).

注意:我不在乎“使用可逆加密存储密码”组策略设置.

奖金

您也可以使用NetUserModalsGet API来检索帐户锁定策略设置:

>帐号锁定持续时间:usrmod3_lockout_duration
>帐号锁定阈值:usrmod3_lockout_threshold
>重设帐号锁定计数器:usrmod3_lockout_observation_window

从而整理所有与密码相关的组策略选项;除了“必须满足复杂性要求”.

为了完整性,假设非域连接的机器(即,没有AD服务器进行查询,没有RSOP查询等).

这是可以使用SAM( Security Account Manager)API.

这个API(由SAMLIB.DLL提供)没有直接记录(没有标题,没有SDK),但是使用它的“协议”在这里记录:[MS-SAMR]: Security Account Manager (SAM) Remote Protocol (Client-to-Server),你只需要删除描述的SamrXXXX方法中的r.

这里有一个是SamQueryInformationDomain(和相关的SamSetinformationDomain),它会给你一个DOMAIN_PASSWORD_INFORMATION的结构

typedef struct _DOMAIN_PASSWORD_informatION {
   unsigned short MinPasswordLength;
   unsigned short PasswordHistoryLength;
   unsigned long PasswordProperties;
   OLD_LARGE_INTEGER MaxPasswordAge;
   OLD_LARGE_INTEGER MinPasswordAge;
 } DOMAIN_PASSWORD_informatION,

PasswordProperties会员可以包含DOMAIN_PASSWORD_COMPLEX标志:

DOMAIN_PASSWORD_COMPLEX
0x00000001
The server enforces password complexity policy. See section 3.1.1.7.2 for details of the password policy.

我提供了一些C#示例来检查这个.

首先,转储当前机器的SAM服务器所服务的所有域的策略:

using (SamServer server = new SamServer(null,SamServer.SERVER_ACCESS_MASK.SAM_SERVER_ENUMERATE_DOMAINS | SamServer.SERVER_ACCESS_MASK.SAM_SERVER_LOOKUP_DOMAIN))
        {
            foreach (string domain in server.EnumerateDomains())
            {
                Console.WriteLine("domain: " + domain);

                var sid = server.GetDomainSid(domain);
                Console.WriteLine(" sid: " + sid);

                var pi = server.GetDomainPasswordinformation(sid);
                Console.WriteLine(" MaxPasswordAge: " + pi.MaxPasswordAge);
                Console.WriteLine(" MinPasswordAge: " + pi.MinPasswordAge);
                Console.WriteLine(" MinPasswordLength: " + pi.MinPasswordLength);
                Console.WriteLine(" PasswordHistoryLength: " + pi.PasswordHistoryLength);
                Console.WriteLine(" PasswordProperties: " + pi.PasswordProperties);
            }
        }

第二个读取并更新当前机器域的策略:

using (SamServer server = new SamServer(null,SamServer.SERVER_ACCESS_MASK.SAM_SERVER_ALL_ACCESS))
        {
            var sid = server.GetDomainSid(Environment.MachineName);
            var pi = server.GetDomainPasswordinformation(sid);

            // remove password complexity
            pi.PasswordProperties &= ~SamServer.PASSWORD_PROPERTIES.DOMAIN_PASSWORD_COMPLEX;
            server.SetDomainPasswordinformation(sid,pi);
        }

这是SamServer实用程序:

public sealed class SamServer : Idisposable
{
    private IntPtr _handle;

    public SamServer(string name,SERVER_ACCESS_MASK access)
    {
        Name = name;
        Check(SamConnect(new UNICODE_STRING(name),out _handle,access,IntPtr.Zero));
    }

    public string Name { get; private set; }

    public void dispose()
    {
        if (_handle != IntPtr.Zero)
        {
            SamCloseHandle(_handle);
            _handle = IntPtr.Zero;
        }
    }

    public void SetDomainPasswordinformation(SecurityIdentifier domainSid,DOMAIN_PASSWORD_informatION passwordinformation)
    {
        if (domainSid == null)
            throw new ArgumentNullException("domainSid");

        byte[] sid = new byte[domainSid.BinaryLength];
        domainSid.GetBinaryForm(sid,0);

        IntPtr domain;
        Check(SamOpenDomain(_handle,DOMAIN_ACCESS_MASK.DOMAIN_WRITE_PASSWORD_ParaMS,sid,out domain));
        IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(passwordinformation));
        Marshal.StructuretoPtr(passwordinformation,info,false);
        try
        {
            Check(SamSetinformationDomain(domain,DOMAIN_informatION_CLASS.DomainPasswordinformation,info));
        }
        finally
        {
            Marshal.FreeHGlobal(info);
            SamCloseHandle(domain);
        }
    }

    public DOMAIN_PASSWORD_informatION GetDomainPasswordinformation(SecurityIdentifier domainSid)
    {
        if (domainSid == null)
            throw new ArgumentNullException("domainSid");

        byte[] sid = new byte[domainSid.BinaryLength];
        domainSid.GetBinaryForm(sid,DOMAIN_ACCESS_MASK.DOMAIN_READ_PASSWORD_ParaMETERS,out domain));
        IntPtr info = IntPtr.Zero;
        try
        {
            Check(SamQueryinformationDomain(domain,out info));
            return (DOMAIN_PASSWORD_informatION)Marshal.PtrToStructure(info,typeof(DOMAIN_PASSWORD_informatION));
        }
        finally
        {
            SamFreeMemory(info);
            SamCloseHandle(domain);
        }
    }

    public SecurityIdentifier GetDomainSid(string domain)
    {
        if (domain == null)
            throw new ArgumentNullException("domain");

        IntPtr sid;
        Check(SamLookupDomainInSamServer(_handle,new UNICODE_STRING(domain),out sid));
        return new SecurityIdentifier(sid);
    }

    public IEnumerable<string> EnumerateDomains()
    {
        int cookie = 0;
        while (true)
        {
            IntPtr info;
            int count;
            var status = SamEnumerateDomainsInSamServer(_handle,ref cookie,out info,1,out count);
            if (status != NTSTATUS.STATUS_SUCCESS && status != NTSTATUS.STATUS_MORE_ENTRIES)
                Check(status);

            if (count == 0)
                break;

            UNICODE_STRING us = (UNICODE_STRING)Marshal.PtrToStructure(info + 8,typeof(UNICODE_STRING));
            SamFreeMemory(info);
            yield return us.ToString();
        }
    }

    private enum DOMAIN_informatION_CLASS
    {
        DomainPasswordinformation = 1,}

    [Flags]
    public enum PASSWORD_PROPERTIES
    {
        DOMAIN_PASSWORD_COMPLEX = 0x00000001,DOMAIN_PASSWORD_NO_ANON_CHANGE = 0x00000002,DOMAIN_PASSWORD_NO_CLEAR_CHANGE = 0x00000004,DOMAIN_LOCKOUT_ADMINS = 0x00000008,DOMAIN_PASSWORD_STORE_CLEARTEXT = 0x00000010,DOMAIN_REFUSE_PASSWORD_CHANGE = 0x00000020,}

    [Flags]
    private enum DOMAIN_ACCESS_MASK
    {
        DOMAIN_READ_PASSWORD_ParaMETERS = 0x00000001,DOMAIN_WRITE_PASSWORD_ParaMS = 0x00000002,DOMAIN_READ_OTHER_ParaMETERS = 0x00000004,DOMAIN_WRITE_OTHER_ParaMETERS = 0x00000008,DOMAIN_CREATE_USER = 0x00000010,DOMAIN_CREATE_GROUP = 0x00000020,DOMAIN_CREATE_ALIAS = 0x00000040,DOMAIN_GET_ALIAS_MEMBERSHIP = 0x00000080,DOMAIN_LIST_ACCOUNTS = 0x00000100,DOMAIN_LOOKUP = 0x00000200,DOMAIN_ADMINISTER_SERVER = 0x00000400,DOMAIN_ALL_ACCESS = 0x000F07FF,DOMAIN_READ = 0x00020084,DOMAIN_WRITE = 0x0002047A,DOMAIN_EXECUTE = 0x00020301
    }

    [Flags]
    public enum SERVER_ACCESS_MASK
    {
        SAM_SERVER_CONNECT = 0x00000001,SAM_SERVER_SHUTDOWN = 0x00000002,SAM_SERVER_INITIALIZE = 0x00000004,SAM_SERVER_CREATE_DOMAIN = 0x00000008,SAM_SERVER_ENUMERATE_DOMAINS = 0x00000010,SAM_SERVER_LOOKUP_DOMAIN = 0x00000020,SAM_SERVER_ALL_ACCESS = 0x000F003F,SAM_SERVER_READ = 0x00020010,SAM_SERVER_WRITE = 0x0002000E,SAM_SERVER_EXECUTE = 0x00020021
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DOMAIN_PASSWORD_informatION
    {
        public short MinPasswordLength;
        public short PasswordHistoryLength;
        public PASSWORD_PROPERTIES PasswordProperties;
        private long _maxPasswordAge;
        private long _minPasswordAge;

        public TimeSpan MaxPasswordAge
        {
            get
            {
                return -new TimeSpan(_maxPasswordAge);
            }
            set
            {
                _maxPasswordAge = value.Ticks;
            }
        }

        public TimeSpan MinPasswordAge
        {
            get
            {
                return -new TimeSpan(_minPasswordAge);
            }
            set
            {
                _minPasswordAge = value.Ticks;
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct UNICODE_STRING : Idisposable
    {
        public ushort Length;
        public ushort MaximumLength;
        private IntPtr Buffer;

        public UNICODE_STRING(string s)
            : this()
        {
            if (s != null)
            {
                Length = (ushort)(s.Length * 2);
                MaximumLength = (ushort)(Length + 2);
                Buffer = Marshal.StringToHGlobalUni(s);
            }
        }

        public void dispose()
        {
            if (Buffer != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(Buffer);
                Buffer = IntPtr.Zero;
            }
        }

        public override string ToString()
        {
            return Buffer != IntPtr.Zero ? Marshal.PtrToStringUni(Buffer) : null;
        }
    }

    private static void Check(NTSTATUS err)
    {
        if (err == NTSTATUS.STATUS_SUCCESS)
            return;

        throw new Win32Exception("Error " + err + " (0x" + ((int)err).ToString("X8") + ")");
    }

    private enum NTSTATUS
    {
        STATUS_SUCCESS = 0x0,STATUS_MORE_ENTRIES = 0x105,STATUS_INVALID_HANDLE = unchecked((int)0xC0000008),STATUS_INVALID_ParaMETER = unchecked((int)0xC000000D),STATUS_ACCESS_DENIED = unchecked((int)0xC0000022),STATUS_OBJECT_TYPE_MISMATCH = unchecked((int)0xC0000024),STATUS_NO_SUCH_DOMAIN = unchecked((int)0xC00000DF),}

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamConnect(UNICODE_STRING ServerName,out IntPtr ServerHandle,SERVER_ACCESS_MASK DesiredAccess,IntPtr ObjectAttributes);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamCloseHandle(IntPtr ServerHandle);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamFreeMemory(IntPtr Handle);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamOpenDomain(IntPtr ServerHandle,DOMAIN_ACCESS_MASK DesiredAccess,byte[] DomainId,out IntPtr DomainHandle);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamLookupDomainInSamServer(IntPtr ServerHandle,UNICODE_STRING name,out IntPtr DomainId);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamQueryinformationDomain(IntPtr DomainHandle,DOMAIN_informatION_CLASS DomaininformationClass,out IntPtr Buffer);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamSetinformationDomain(IntPtr DomainHandle,IntPtr Buffer);

    [DllImport("samlib.dll",CharSet = CharSet.Unicode)]
    private static extern NTSTATUS SamEnumerateDomainsInSamServer(IntPtr ServerHandle,ref int EnumerationContext,out IntPtr EnumerationBuffer,int PreferedMaximumLength,out int CountReturned);
}

Windows – 如何编程检查“密码必须满足复杂性要求”组策略设置?的更多相关文章

  1. ios – Swift:不符合协议NSCoding

    我正在尝试在swift中使用NSCoding协议,但是似乎无法弄清楚为什么编译器会抱怨当我实现所需的方法时它“不符合协议NSCoding”:这是一个bug还是我只是想念一些东西?解决方法在报告导航器中的详细编译器消息中可以看到,您的方法未正确声明:此外,initWithCoder方法必须标记为必需:在Swift3中,所需的方法是

  2. 探索:测试 Swift 中的 ErrorType

    最后我们以一个说明样例、以及一些有用的资源结尾如何实现ErrorType协议如果跳转到Swift标准库中ErrorType定义的位置,我们就会发现它并没有包含明显的要求。我们最初的想法可能是,也许ErrorType是一种特殊类型,编译器以特殊的方式来对它进行支持,而且只能用Swift原生的枚举来实现。更新:从Xcode7beta5版本开始,我们可能不需要花费其他精力就可以为结构体和类实现ErrorType协议。允许结构体和类实现ErrorType协议。通过LLDB进一步调查发现这个协议有一些隐藏的要求。

  3. swift – 无法在Simulator中运行应用程序:运行时遇到错误(Domain = LaunchServicesError,Code = 0)

    我在配置文件出现问题后无法在模拟器中运行我的应用程序。我在xcode6–beta4中做快速编码。这是很好的在证书的配置文件的麻烦。我已经尝试清洗构建。检查命令行到xCode6-beta4运行。检查构建部署,设置为7.0,所以swift将不会抱怨兼容性修复配置中的错误。请建议其他方法来修复此错误。谢谢如果您的扩展程序的捆绑ID不带应用的捆绑ID,则会发生这种情况。

  4. 在Swift中创建一个新的NSError(拒绝PromiseKit中的Promise)

    我一直在试图使用PromiseKit,而我坚持拒绝承诺。承诺拒绝通过调用具有NSError作为参数的拒绝功能来完成。简单地得到一个NSError的实例会帮助我。您在此代码中有两个问题:>NSError的所有初始化参数都有externalname。>空字典文字是[:],而不是[]。[]是为Array尝试:或者,如果您没有任何userInfo,您可能希望通过为零。

  5. 确定字符串是否包含Swift中的一个字符的最佳方法是什么?

    我需要确定字符串是否包含我定义的自定义集中的任何字符.我从this发现你可以使用rangeOfString来确定一个字符串是否包含另一个字符串.这当然也适用于字符,如果你一次测试每个字符一个.我想知道最好的办法是做什么.您可以创建一个包含自定义字符集的CharacterSet然后根据此字符集测试成员资格:Swift3:对于不区分大小写的比较,请使用.Swift2:Swift1.2

  6. swift – Alamofire请求cookies

    我是初学者,我无法弄清楚如何使用Alamofire制作.GET请求.我设法用其他Web服务(登录)执行此操作,因为它需要参数参数:然后:在回复标题中我得到一些信息:它的类型为[NSObject:AnyObject]如何将该信息存储在NSURLDefaults中并准备有效的请求参数?我需要所有字段还是只需要Set-Cookie?

  7. android – 使用改造下载图像文件

    解决方法问题是响应中的内容类型标头包含一个虚假的字符集:Retrofit看到了这一点,并推断响应是它可以记录的文本.您应该将问题报告给服务器的管理员.如果您将问题报告给GitHub上的Retrofit问题跟踪器,我们可能会从此问题中恢复而不是崩溃.

  8. android – 如何知道标签是否存在?

    我认为有必要插入一个按钮来检查标签是否存在.我在我的活动中添加了“前台调度系统”,但是我仍然不明白如果标签存在与否,如何显示消息,在使用读写方法之前要检查什么?解决方法扫描新的NFC标签后立即调用onNewIntent.例如,如果您想要写入每个扫描的标记,则onNewIntent()方法将如下所示:你的writeTag方法当然还没有使用它给出的字符串,但你可能知道.如果您想要保持最新的布尔值以检查可用标记,请执行以下操作:

  9. Android:java.net.protocolException不支持输出

    我用错了吗?

  10. Laravel路由研究之domain解决多域名问题的方法示例

    这篇文章主要介绍了Laravel 路由研究之domain解决多域名问题的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部