Windows – 如何编程检查“密码必须满足复杂性要求”组策略设置
窗口有五个与密码安全相关的策略设置:
>强制密码历史记录 我知道如何使用 >强制密码历史记录:usrmod0_password_hist_len 我也知道,WMI的RSOP(“结果集策略”)不合适,as it only works on a domain.我肯定不会去crawling through an undocumented binary blob(即我想要支持的方式). 注意:我不在乎“使用可逆加密存储密码”组策略设置. 奖金 您也可以使用NetUserModalsGet API来检索帐户锁定策略设置: >帐号锁定持续时间:usrmod3_lockout_duration 从而整理所有与密码相关的组策略选项;除了“必须满足复杂性要求”. 为了完整性,假设非域连接的机器(即,没有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-xp – Windows XP挂在登录屏幕上
- 冷高轮时间屏保
- active-directory – 当删除AD用户帐户时,Windows是否为安全
- 使用window.onbeforeunload事件中的window.event.keyCode在
- character-encoding – Go:使用windows-1252编码写入文件
- 如何在Windows上编写C FireFox 3插件(不是扩展名)?
- 带有非托管DLL的C#应用??程序冻结了整个系统
- 网站为什么时快时慢
- windows-server-2008-r2 – 如何确定谁安装了程序?
- windows – C try-catch块没有捕获硬件异常
- 启动 – 无盘服务器2012上的第二个NIC“无法正常
- windows-server-2008 – IIS SMTP服务器是否足以
- windows-server-2008 – 无法在带有PERC H710 Mi
- windows-server-2008 – schtasks – 创建没有按
- windows-phone-7 – 如何删除IE移动浏览器的点击
- 在Windows中同步读取stdin
- 在我的Windows 2008 DNS / DHCP服务器上注册我的
- microsoft-ui-automation – UI Automation – 基
- windows-phone-7 – Windows Phone:确定设备(制
- windows – WinUSB应用程序或用户模式驱动程序,作