This function is handy for resolving dsHeuristics values:
PowerShell
function Resolve-DsHeuristics {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false, ValueFromPipeline = $true)]
[ValidatePattern("^[0-9a-f]+$")]
[string]$Heuristics
)
if (-not [string]::IsNullOrEmpty($Heuristics)) {
$res = @()
for($pos = 1; $pos -le $Heuristics.Length; $pos++) {
$char = $Heuristics[($pos - 1)]
$item = [PSCustomObject]@{
'Position' = $pos
'Character' = $char
'Name' = ''
'Value' = $false
'IsValid' = $true
'IsDefault' = $true
'Behavior' = ''
'URI' = ''
'SupportedOn' = 'all versions'
}
$addItem = $true
switch ($pos) {
1 {
$item.Name = 'fSupFirstLastANR'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.Behavior = 'Ambiguous Name Resolution will not include search by "Firstname Lastname"'
$item.IsDefault = $false
} else {
$item.Behavior = 'Ambiguous Name Resolution will include search by "Firstname Lastname"'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1a9177f4-0272-4ab8-aa22-3c3eafd39e4b'
}
2 {
$item.Name = 'fSupLastFirstANR'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.Behavior = 'Ambiguous Name Resolution will not include search by "Lastname Firstname"'
$item.IsDefault = $false
} else {
$item.Behavior = 'Ambiguous Name Resolution will include search by "Lastname Firstname"'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1a9177f4-0272-4ab8-aa22-3c3eafd39e4b'
}
3 {
$item.Name = 'fDoListObject'
$item.Value = ($char -eq '1')
if ($item.Value) {
$item.Behavior = 'The "List Object" right will be enforced and children will be hidden if the searcher does not have the DS_LIST_OBJECT right on the parent'
$item.IsDefault = $false
} else {
$item.Behavior = 'The "List Object" right will not be enforced and children willl be shown regardless of the DS_LIST_OBJECT right on the parent'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/990fb975-ab31-4bc1-8b75-5da132cd4584'
}
4 {
$item.Name = 'fDoNickRes'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.Behavior = 'Ambiguous Name Resolution request via MAPI will attempt an exact match against the MAPI nickname'
$item.IsDefault = $false
} else {
$item.Behavior = 'MAPI nickname will not be matched by Ambiguous Name Resolution'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1a9177f4-0272-4ab8-aa22-3c3eafd39e4b'
}
5 {
$item.Name = 'fLDAPUsePermMod'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.Behavior = 'LDAP will use the LDAP_SERVER_PERMISSIVE_MODIFY control (return success even if no modification is performed)'
$item.IsDefault = $false
} else {
$item.Behavior = 'LDAP will use strict modification behavior and return an error if no modifications are to be performed, like deleting an attribute that is not present.'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/49cdb1e3-3baa-4c7c-8cde-7c26b13d3ba7'
}
6 {
$item.Name = 'ulHideDSID'
switch ($char) {
'0' {
$item.Value = 0
$item.Behavior = 'DSID will always be returned'
}
'1' {
$item.Value = 1
$item.IsDefault = $false
$item.Behavior = 'DSID will only be returned if it does not reveal the identity of the object otherwise invisible to the client'
}
default {
$item.Value = -1
$item.IsDefault = $false
$item.Behavior = 'DSID will NOT be returned'
}
}
}
7 {
$item.Name = 'fLDAPBlockAnonOps'
$item.Value = ($char -ne '2')
if ($item.Value) {
$item.Behavior = 'LDAP will only allow searching RootDSE anonymously, regardless of ACL'
} else {
$item.IsDefault = $false
$item.Behavior = 'LDAP will allow anonymous searches if the ACLs permit them'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/4e11a7e6-e18c-46e4-a781-3ca2b4de6f30'
$item.SupportedOn = 'DC FL 2003 and newer'
}
8 {
$item.Name = 'fAllowAnonNSPI'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'Allow anonymous NSPI (RPC) calls'
} else {
$item.Behavior = 'Reject anonymous NSPI (RPC) calls'
}
}
9 {
$item.Name = 'fUserPwdSupport'
$item.Value = ($char -notin ('0','2'))
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'Disable access to userPassword attribute, regardless of permissions'
} else {
$item.Behavior = 'Allow access to userPassword attribute, ACLs permitting'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/4e11a7e6-e18c-46e4-a781-3ca2b4de6f30'
}
10 {
$item.Name = 'tenthChar'
$item.Value = ($char -eq '1')
if ($item.Value) {
$item.Behavior = 'If heuristics beyond the 9th char are to be set, the 10th char must have a value of 1'
} else {
$item.IsDefault = $false
$item.IsValid = $false
$item.Behavior = 'If 10th char is anything else than 1, the server should reject the update!'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/76df255d-dc67-4c1f-adc6-1e5b60021304'
}
11 {
$item.Name = 'fSpecifyGUIDOnAdd'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'On adding an object, specifying its GUID is allowed'
} else {
$item.Behavior = 'Specifying GUIDs is not allowed for add operations'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/7dfeb38c-3cb9-4215-ae1c-ef209fd251ae'
}
12 {
$item.Name = 'fDontStandardizeSDs'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'The order of ACEs supplied by the client is preserved'
} else {
$item.Behavior = 'ACEs are sorted according to the ordering rules'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/081c41f0-4c8d-4ab0-971d-77ec2504375a'
}
13 {
$item.Name = 'fAllowPasswordOperationsOverNonSecureConnection'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'Password operations are allowed without encryption (valid for ADLDS only!)'
} else {
$item.Behavior = 'Password operations require encryption (valid for ADLDS only!)'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/6e803168-f140-4d23-b2d3-c3a8ab5917d2'
}
14 {
$item.Name = 'fDontPropagateOnNoChangeUpdate'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'ntSecurityDescriptor is propagated to descendant objects on change, even if the new value is bitwise identical to the old one'
} else {
$item.Behavior = 'Changes in ntSecurityDescriptor where the old and the new value are bitwise identical, do not trigger propagation'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/b645c125-a7da-4097-84a1-2fa7cea07714#gt_b581857f-39aa-4979-876b-daba67a40f15'
$item.SupportedOn = 'Windows Server 2008 and newer'
}
15 {
$item.Name = 'fComputeANRStats'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'ANR searches are optimized using cardianlity estimates'
} else {
$item.Behavior = 'ANR searches are not optimized using cardinality from previous searches'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1a9177f4-0272-4ab8-aa22-3c3eafd39e4b'
}
16 {
$item.Name = 'dwAdminSDExMask'
$item.Value = @()
$mask = "0x$char" -as [int]
if (($mask -band 1) -gt 0) { $item.Value += 'ACCOUNT_OPS' }
if (($mask -band 2) -gt 0) { $item.Value += 'SYSTEM_OPS' }
if (($mask -band 4) -gt 0) { $item.Value += 'PRINT_OPS' }
if (($mask -band 8) -gt 0) { $item.Value += 'BACKUP_OPS' }
if ($item.Value.Count -gt 0) {
$item.IsDefault = $false
$item.Behavior = ('The following groups will be excluded aus SDPROP: {0}' -f ($item.Value -join ','))
} else {
$item.Behavior = 'All privileged groups are included in SDPROP'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/dd3d29f3-8e1e-4e8c-a210-9eaef3abd628'
}
17 {
$item.Name = 'fKVNOEmuW2K'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'msDS-KeyVersionNumber will always equal 1 (W2K emulation)'
} else {
$item.Behavior = 'msDS-KeyVersionNumber will be read from object'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/cb85ccdf-6469-42d5-a61c-ebae09b72e9d'
}
18 {
$item.Name = 'fLDAPBypassUpperBoundsOnLimits'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'DCs will bypass implementation-dependent limits on LDAP policies'
} else {
$item.Behavior = 'DCs will respect implementation-dependent limits on LDAP policies'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3f0137a1-63df-400c-bf97-e1040f055a99'
$item.SupportedOn = 'Windows Server 2008 and newer'
}
19 {
$item.Name = 'fDisableAutoIndexingOnSchemaUpdate'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'Index creation is triggered by index-related changes to the searchFlags attribute'
} else {
$item.Behavior = 'Index creation can be delayed upon detection of index-related changes to the searchFlags attribute until either an administrator issues the schemaUpdateNow rootDSE modify operation, the DC is rebooted, or an implementation-dependent time period has elapsed'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3f0137a1-63df-400c-bf97-e1040f055a99'
$item.SupportedOn = 'Windows Server 2012 and newer'
}
20 {
$item.Name = 'twentiethChar'
$item.Value = ($char -eq '2')
if ($item.Value) {
$item.Behavior = 'If heuristics beyond the 19th char are to be set, the 20th char must have a value of 2'
} else {
$item.IsDefault = $false
$item.IsValid = $false
$item.Behavior = 'If 20th char is anything else than 2, the server should reject the update!'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/76df255d-dc67-4c1f-adc6-1e5b60021304'
}
21 {
$item.Name = 'DoNotVerifyUPNAndOrSPNUniqueness'
$item.Value = @()
$mask = "0x$char" -as [int]
if (($mask -band 1) -eq 0) { $item.Value += 'UPN' }
if (($mask -band 2) -eq 0) { $item.Value += 'SPN' }
if (($mask -band 4) -eq 0) { $item.Value += 'SPN alias' }
if ($item.Value.Count -gt 0) {
$item.IsDefault = $false
$item.Behavior = ('The following uniqueness consraints will not be checked prior to submitting the change: {0}' -f $item.Value -join ',')
} else {
$item.Behavior = 'All uniqueness constraints will be checked before submitting'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3c154285-454c-4353-9a99-fb586e806944'
$item.SupportedOn = 'Windows Server 2012R2 and newer'
}
22 {
if ($pos -lt $Heuristics.Length) {
$char = ('0x{0}{1}' -f $Heuristics[$pos -1], $Heuristics[$pos])
$item.Character = ('{0}{1}' -f $Heuristics[$pos -1], $Heuristics[$pos])
$item.Value = $char
$minver = $char -as [int]
$item.Name = 'MinimumGetChangesRequestVersion'
if ($minver -eq 0) {
$item.Behavior = 'No restrictions on GETCHGREQ version will be imposed'
} else {
$item.IsDefault = $false
$item.Behavior = ('GETCHGREQ must have the minimum version of {0}' -f $minver)
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-drsr/20ddf6d7-ac4e-4e16-8910-fbeca8f6e980'
} else {
$item.Name = '<MISSING DATA - position 23 must be set as well!>'
$item.IsValid = $false
$item.IsDefault = $false
}
}
23 {
Write-Verbose "Skipping byte 23 since it's paired with 22!"
$addItem = $false
}
24 {
if ($pos -lt $Heuristics.Length) {
$char = ('0x{0}{1}' -f $Heuristics[$pos -1], $Heuristics[$pos])
$item.Character = ('{0}{1}' -f $Heuristics[$pos -1], $Heuristics[$pos])
$item.Value = $char
$minver = $char -as [int]
$item.Name = 'MinimumGetChangesReplyVersion'
if ($minver -eq 0) {
$item.Behavior = 'No restrictions on GETCHGREPLY version will be imposed'
} else {
$item.IsDefault = $false
$item.Behavior = ('GETCHGREPLY must have the minimum version of {0}' -f $minver)
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-drsr/20ddf6d7-ac4e-4e16-8910-fbeca8f6e980'
} else {
$item.Name = '<MISSING DATA - position 25 must be set as well!>'
$item.IsValid = $false
$item.IsDefault = $false
}
}
25 {
Write-Verbose "Skipping byte 25 since it's paired with 24!"
$addItem = $false
}
26 {
$item.Name = 'fLoadV1AddressBooksOnlySetting'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'MAPI address book is calculated using V1 attributes'
} else {
$item.Behavior = 'MAPI address book is calculated using V2 attributes'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3f0137a1-63df-400c-bf97-e1040f055a99'
$item.SupportedOn = 'Windows Client/Server 1903 and newer'
}
27 {
$item.Name = 'fTreatTokenGroupsAsLDAPTransitiveAttribute'
$item.Value = ($char -ne '0')
if ($item.Value) {
$item.IsDefault = $false
$item.Behavior = 'LDAP Policy "MaxValueRangeTransitive" is respected for token groups'
} else {
$item.Behavior = 'LDAP Policy "MaxValueRange" is respected for token groups'
}
$item.URI = 'https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/01002598-92db-4c59-822e-b22f53168c90'
$item.SupportedOn = 'Windows Client/Server 1903 and newer'
}
28 {
$item.Name = 'AttributeAuthorizationOnLDAPAdd'
$enforcementDateHasPassed = ((Get-Date) -gt (Get-Date -Year 2023 -Month 4 -Day 11))
switch ($char) {
"0" {
$item.Value = 0
$item.Behavior = 'KB5008383 LDAP Add AuthZ verification disabled (not supported after 2023-04-11)'
$item.IsValid = (-not $enforcementDateHasPassed)
$item.IsDefault = (-not $enforcementDateHasPassed)
}
"2" {
$item.IsDefault = $false
$item.Value = 2
$item.Behavior = 'KB5008383 LDAP Add AuthZ enforcement mode disabled, updated auditing disabled'
}
default {
$item.Value = 1
$item.IsDefault = $enforcementDateHasPassed
$item.Behavior = 'KB5008383 LDAP Add AuthZ enforcement mode'
}
}
$item.URI = 'https://support.microsoft.com/en-us/topic/kb5008383-active-directory-permissions-updates-cve-2021-42291-536d5555-ffba-4248-a60e-d6cbc849cde1'
$item.SupportedOn = 'Windows Server 2008R2 and higher'
}
29 {
$item.Name = 'BlockOwnerImplicitRights'
$enforcementDateHasPassed = ((Get-Date) -gt (Get-Date -Year 2023 -Month 4 -Day 11))
switch ($char) {
"0" {
$item.Value = 0
$item.Behavior = 'KB5008383 Owner Implicit Rights Audit enabled'
$item.IsDefault = (-not $enforcementDateHasPassed)
}
"2" {
$item.IsDefault = $false
$item.Value = 2
$item.Behavior = 'KB5008383 Owner Implicit Rights enforcement mode disabled'
}
default {
$item.Value = 1
$item.IsDefault = $enforcementDateHasPassed
$item.Behavior = 'KB5008383 Owner Implicit Rights enforcement mode'
}
}
$item.URI = 'https://support.microsoft.com/en-us/topic/kb5008383-active-directory-permissions-updates-cve-2021-42291-536d5555-ffba-4248-a60e-d6cbc849cde1'
$item.SupportedOn = 'Windows Server 2008R2 and higher'
}
default {
$item.Value = $null
$item.IsValid = $false
$item.IsDefault = $false
$item.Behavior = 'This position in the dsHeuristics string has not yet been assigned'
}
}
if ($addItem) {
$res += $item
}
}
return $res
}
}