Powershell/Private/RegistryKey/Test-DATParentPermission.ps1
|
function Test-DATParentPermission { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$DirectoryPath, [Parameter(Mandatory = $true)] [string]$UserSID ) $requiredSIDs = @( 'S-1-5-18', # NT AUTHORITY\SYSTEM 'S-1-5-32-544', # BUILTIN\Administrators $UserSID ) $missingIdentities = [System.Collections.Generic.List[string]]::new() $insufficientRights = [System.Collections.Generic.List[PSCustomObject]]::new() function local:Get-IdentityName { param([string]$Sid) try { return (New-Object System.Security.Principal.SecurityIdentifier($Sid)).Translate([System.Security.Principal.NTAccount]).Value } catch { return $Sid } } function local:Test-DirectoryTraverseRight { param([System.Security.AccessControl.FileSystemRights]$Rights) $rightsValue = [int]$Rights $fullControl = [int][System.Security.AccessControl.FileSystemRights]::FullControl $modify = [int][System.Security.AccessControl.FileSystemRights]::Modify $readAndExecute = [int][System.Security.AccessControl.FileSystemRights]::ReadAndExecute $traverse = [int][System.Security.AccessControl.FileSystemRights]::Traverse $listDirectory = [int][System.Security.AccessControl.FileSystemRights]::ListDirectory $read = [int][System.Security.AccessControl.FileSystemRights]::Read if (($rightsValue -band $fullControl) -eq $fullControl) { return $true } if (($rightsValue -band $modify) -eq $modify) { return $true } if (($rightsValue -band $readAndExecute) -eq $readAndExecute) { return $true } if ((($rightsValue -band $traverse) -eq $traverse) -and ((($rightsValue -band $listDirectory) -eq $listDirectory) -or (($rightsValue -band $read) -eq $read))) { return $true } return $false } function local:Get-MissingTraverseRight { param([System.Security.AccessControl.FileSystemRights]$Rights) $missing = [System.Collections.Generic.List[string]]::new() if (-not (Test-DirectoryTraverseRight -Rights $Rights)) { $requiredRights = @( [System.Security.AccessControl.FileSystemRights]::Traverse, [System.Security.AccessControl.FileSystemRights]::ListDirectory, [System.Security.AccessControl.FileSystemRights]::ReadAndExecute, [System.Security.AccessControl.FileSystemRights]::Read ) foreach ($requiredRight in $requiredRights) { if (([int]$Rights -band [int]$requiredRight) -ne [int]$requiredRight) { $missing.Add($requiredRight.ToString()) } } } return $missing } function local:Test-IsApplicableAce { param($Rule) return $Rule.PropagationFlags -ne [System.Security.AccessControl.PropagationFlags]::InheritOnly } function local:Get-EffectiveFileSystemRight { param( [array]$AllowRules, [array]$DenyRules ) $allowMask = 0 $denyMask = 0 foreach ($rule in $AllowRules) { $allowMask = $allowMask -bor [int]$rule.FileSystemRights } foreach ($rule in $DenyRules) { $denyMask = $denyMask -bor [int]$rule.FileSystemRights } return [System.Security.AccessControl.FileSystemRights]($allowMask -band (-bnot $denyMask)) } $acl = Get-Acl -Path $DirectoryPath -ErrorAction SilentlyContinue if (-not $acl) { return [PSCustomObject]@{ IsValid = $false MissingIdentities = @('Directory not accessible or does not exist') InsufficientRights = @() } } foreach ($sid in $requiredSIDs) { $identityName = Get-IdentityName -Sid $sid $applicableAllowRules = @() $applicableDenyRules = @() foreach ($rule in $acl.Access) { try { $ruleSid = $rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value } catch { $ruleSid = $rule.IdentityReference.Value } if ($ruleSid -ne $sid -or -not (Test-IsApplicableAce -Rule $rule)) { continue } if ($rule.AccessControlType -eq 'Allow') { $applicableAllowRules += $rule } elseif ($rule.AccessControlType -eq 'Deny') { $applicableDenyRules += $rule } } if ($applicableAllowRules.Count -eq 0) { $missingIdentities.Add($identityName) continue } $effectiveRights = Get-EffectiveFileSystemRight -AllowRules $applicableAllowRules -DenyRules $applicableDenyRules if (-not (Test-DirectoryTraverseRight -Rights $effectiveRights)) { $missingRights = Get-MissingTraverseRight -Rights $effectiveRights $insufficientRights.Add([PSCustomObject]@{ Identity = $identityName SID = $sid MissingRights = @($missingRights) }) } } return [PSCustomObject]@{ IsValid = ($missingIdentities.Count -eq 0 -and $insufficientRights.Count -eq 0) MissingIdentities = @($missingIdentities) InsufficientRights = @($insufficientRights) } } |