How to Fix Corrupted ACLs, Permission Denials, and Long Path Issues in Windows File Shares


5 views

When dealing with legacy Windows file shares, administrators often encounter three major issues:

  • Corrupted ACLs: Disordered or malformed Access Control Entries
  • Permission denials: Explicit denies for SYSTEM or Administrators
  • Path length limitations: Exceeding MAX_PATH (260 characters)

Here's a PowerShell script that handles all three scenarios:


# Fix-Permissions.ps1
param (
    [Parameter(Mandatory=$true)]
    [string]$Path
)

function Repair-LongPath {
    param ($itemPath)
    if ($itemPath.Length -gt 240) {
        return "\\?\$($itemPath.Replace('/','\'))"
    }
    return $itemPath
}

function Reset-Permissions {
    param ($item)
    $acl = Get-Acl $item
    $acl.SetAccessRuleProtection($false, $true)
    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        "BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
    )
    $acl.AddAccessRule($rule)
    Set-Acl -Path $item -AclObject $acl
}

$fixedPath = Repair-LongPath $Path

try {
    $acl = Get-Acl $fixedPath -ErrorAction Stop
    if ($acl.Access | Where { $_.AccessControlType -eq "Deny" -and $_.IdentityReference -like "*Administrators*" }) {
        takeown /F $fixedPath /A
        icacls $fixedPath /grant "Administrators:(F)" /T /C
    }
    Reset-Permissions $fixedPath
}
catch {
    if ($_.Exception -like "*cannot find the path*") {
        Write-Warning "Path resolution failed - try UNC or long path prefix"
    }
    elseif ($_.Exception -like "*access is denied*") {
        Write-Warning "Running under SYSTEM context may be required"
        # Alternative using PsExec:
        # psexec -s -i powershell -File "Fix-Permissions.ps1" -Path $fixedPath
    }
}

For particularly problematic items, consider these approaches:

  1. SDDL Manipulation:
    
    $sddl = "D:(A;;FA;;;BA)(A;;FA;;;SY)"
    $acl = Get-Acl -Path $fixedPath
    $acl.SetSecurityDescriptorSddlForm($sddl)
    Set-Acl -Path $fixedPath -AclObject $acl
    
  2. Backup/Restore Method:
    
    robocopy "%temp%\empty" "problem_folder" /mir /xd "problem_folder"
    

When native tools aren't sufficient:

  • SetACL: For granular permission management
    
    setacl -on "X:\problem_folder" -ot file -actn restore -rec cont_obj -bckp "backup.sddl"
    
  • NtfsInfo (Sysinternals): For low-level analysis
    
    ntfsinfo -d X:\problem_folder > acl_analysis.txt
    

To avoid future issues:


# Group Policy recommendation:
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" 
    -Name "LongPathsEnabled" -Value 1

When dealing with legacy file shares in enterprise environments, we frequently encounter three persistent issues:

  • ACL Corruption: Disordered Access Control Entries or invalid security descriptors
  • Permission Denials: Explicit DENY entries for SYSTEM or Administrators
  • Path Length Limitations: Files exceeding MAX_PATH (260 characters) constraints

Here's a comprehensive PowerShell script that addresses all three scenarios:


function Repair-FilePermissions {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Path,
        [switch]$Recursive
    )
    
    # Handle long paths
    if ($Path.Length -gt 240) {
        $Path = "\\?\$($Path.TrimStart('\\'))"
    }

    try {
        $acl = Get-Acl -Path $Path -ErrorAction Stop
        
        # Check for corrupted ACL
        if ($acl.AccessToString -match "Invalid|Unknown") {
            Write-Verbose "Found corrupted ACL at $Path"
            $newAcl = New-Object System.Security.AccessControl.DirectorySecurity
            $newAcl.SetAccessRuleProtection($false, $true)
            Set-Acl -Path $Path -AclObject $newAcl -ErrorAction Stop
        }

        # Verify Administrator access
        $adminRule = $acl.Access | 
            Where-Object { $_.IdentityReference -eq "BUILTIN\Administrators" -and $_.AccessControlType -eq "Deny" }
        
        if ($adminRule) {
            Write-Verbose "Found Administrator deny rule at $Path"
            Takeown.exe /F $Path /A
            Icacls.exe $Path /grant:r "BUILTIN\Administrators:(OI)(CI)F" /T /C
        }

        # Recurse if directory
        if ((Get-Item $Path) -is [System.IO.DirectoryInfo] -and $Recursive) {
            Get-ChildItem -Path $Path | ForEach-Object {
                Repair-FilePermissions -Path $_.FullName -Recursive
            }
        }
    }
    catch {
        Write-Warning "Failed to process $Path : $($_.Exception.Message)"
    }
}

For particularly stubborn cases, we combine our PowerShell approach with Sysinternals utilities:


psexec.exe -i -s cmd.exe /c "takeown /f \"C:\problem_folder\" /r /d y && icacls \"C:\problem_folder\" /reset /t /c /q"

Before making changes, it's crucial to analyze the existing permissions. This script helps identify problematic entries:


function Get-PermissionIssues {
    param ($Path)
    
    $results = @()
    $acl = Get-Acl $Path
    
    foreach ($ace in $acl.Access) {
        if ($ace.AccessControlType -eq "Deny" -and 
            ($ace.IdentityReference -like "*Administrators*" -or 
             $ace.IdentityReference -like "*SYSTEM*")) {
            $results += [pscustomobject]@{
                Path = $Path
                Issue = "Critical Deny Rule"
                Identity = $ace.IdentityReference
            }
        }
        
        if ($ace.IdentityReference -like "*S-1-5-21-*") {
            $results += [pscustomobject]@{
                Path = $Path
                Issue = "Orphaned SID"
                Identity = $ace.IdentityReference
            }
        }
    }
    
    return $results
}

For complex environments, consider these specialized tools:

  • SetACL Studio: Graphical interface for bulk permission management
  • NtfsPermissionsReport: Generates detailed permission analysis reports
  • TreeSize Professional: Identifies permission issues alongside storage analysis

To avoid future problems:

  1. Implement regular permission audits with PowerShell scripts
  2. Establish standardized permission templates
  3. Enable Windows' built-in Access Denied Assistance feature
  4. Monitor for path length issues during file operations

Here's how we might process a problematic share:


# 1. First analyze the share structure
$issues = Get-ChildItem -Path "\\fileserver\share" -Recurse | 
    ForEach-Object { Get-PermissionIssues -Path $_.FullName } | 
    Where-Object { $_.Issue }

# 2. Process each issue
foreach ($item in $issues) {
    Repair-FilePermissions -Path $item.Path -Recursive
}

# 3. Reset inheritance where needed
Get-ChildItem -Path "\\fileserver\share" -Recurse | ForEach-Object {
    icacls $_.FullName /reset /t /c /q
}