setuptestdir.ps1


<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 52d7a324-b4ed-4c89-95fb-64e1df90a240
 
.AUTHOR Paul@sexstone.com
 
.COMPANYNAME Sexstone
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>


<#
 
.DESCRIPTION
use setuptestdir.ps1 to create a demo directory to show script working safely.
Find and fix folders with broken inheritance and unable to be accessed by admin
use fix_no_access_folders.ps1 first, to makde all files visible then use fix_no_access_files.ps1
   
 
 
#>
 
Param()#

"
# create base directorys and copy 2 files into each, 1 file inherited permissions, 1 file unique permissions
# 1:inherited access + subfolder
# 2:inherited access + subfolder - restricted file2 in root
# 3:inherited access + subfolder - unrestricted folder, restricted subfolder, restricted file2 in root and subfolder
# 4:inherited access + subfolder - restricted folder, unrestricted subfolder, restricted file2 in root and subfolder file2
# 5:inherited access + subfolder - restricted folder & subfolder, restricted file2 in root and subfolder
 
total files 5 folder + 5 subfolders * 2 files each = 20 files
    confirmation of setup = ntfs visible 12 files, 22 directories
    visible directories = 1/3 of (dir /s count-2)
 
 
"

$testfolderprefix = "folder" #folder prefix for test folders
$testroot = "c:\acltestroot\"  #where the test files should be created including
$testfileSrc = "c:\temp\testfile.png" #testfile to be copied into every folder as file1 and file 2
$restrictaccount = "Guest" #account that will be used to set as owner and access on restricted files and folder



# **************************************** function set-owner start
Function Set-Owner {
    <#
        .SYNOPSIS
            Changes owner of a file or folder to another user or group.
 
        .DESCRIPTION
            Changes owner of a file or folder to another user or group.
 
        .PARAMETER Path
            The folder or file that will have the owner changed.
 
        .PARAMETER Account
            Optional parameter to change owner of a file or folder to specified account.
 
            Default value is 'Builtin\Administrators'
 
        .PARAMETER Recurse
            Recursively set ownership on subfolders and files beneath given folder.
 
        .NOTES
            Name: Set-Owner
            Author: Boe Prox
            Version History:
                 1.0 - Boe Prox
                    - Initial Version
 
        .EXAMPLE
            Set-Owner -Path C:\temp\test.txt
 
            Description
            -----------
            Changes the owner of test.txt to Builtin\Administrators
 
        .EXAMPLE
            Set-Owner -Path C:\temp\test.txt -Account 'Domain\bprox
 
            Description
            -----------
            Changes the owner of test.txt to Domain\bprox
 
        .EXAMPLE
            Set-Owner -Path C:\temp -Recurse
 
            Description
            -----------
            Changes the owner of all files and folders under C:\Temp to Builtin\Administrators
 
        .EXAMPLE
            Get-ChildItem C:\Temp | Set-Owner -Recurse -Account 'Domain\bprox'
 
            Description
            -----------
            Changes the owner of all files and folders under C:\Temp to Domain\bprox
    #>

    [cmdletbinding(
        SupportsShouldProcess = $True
    )]
    Param (
        [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias('FullName')]
        [string[]]$Path,
        [parameter()]
        [string]$Account = 'Builtin\Administrators',
        [parameter()]
        [switch]$Recurse
    )
    Begin {
        #Prevent Confirmation on each Write-Debug command when using -Debug
        If ($PSBoundParameters['Debug']) {
            $DebugPreference = 'Continue'
        }
        Try {
            [void][TokenAdjuster]
        } Catch {
            $AdjustTokenPrivileges = @"
            using System;
            using System.Runtime.InteropServices;
 
             public class TokenAdjuster
             {
              [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
              internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
              ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
              [DllImport("kernel32.dll", ExactSpelling = true)]
              internal static extern IntPtr GetCurrentProcess();
              [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
              internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
              phtok);
              [DllImport("advapi32.dll", SetLastError = true)]
              internal static extern bool LookupPrivilegeValue(string host, string name,
              ref long pluid);
              [StructLayout(LayoutKind.Sequential, Pack = 1)]
              internal struct TokPriv1Luid
              {
               public int Count;
               public long Luid;
               public int Attr;
              }
              internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
              internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
              internal const int TOKEN_QUERY = 0x00000008;
              internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
              public static bool AddPrivilege(string privilege)
              {
               try
               {
                bool retVal;
                TokPriv1Luid tp;
                IntPtr hproc = GetCurrentProcess();
                IntPtr htok = IntPtr.Zero;
                retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
                tp.Count = 1;
                tp.Luid = 0;
                tp.Attr = SE_PRIVILEGE_ENABLED;
                retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
                retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
                return retVal;
               }
               catch (Exception ex)
               {
                throw ex;
               }
              }
              public static bool RemovePrivilege(string privilege)
              {
               try
               {
                bool retVal;
                TokPriv1Luid tp;
                IntPtr hproc = GetCurrentProcess();
                IntPtr htok = IntPtr.Zero;
                retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
                tp.Count = 1;
                tp.Luid = 0;
                tp.Attr = SE_PRIVILEGE_DISABLED;
                retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
                retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
                return retVal;
               }
               catch (Exception ex)
               {
                throw ex;
               }
              }
             }
"@

            Add-Type $AdjustTokenPrivileges
        }

        #Activate necessary admin privileges to make changes without NTFS perms
        [void][TokenAdjuster]::AddPrivilege("SeRestorePrivilege") #Necessary to set Owner Permissions
        [void][TokenAdjuster]::AddPrivilege("SeBackupPrivilege") #Necessary to bypass Traverse Checking
        [void][TokenAdjuster]::AddPrivilege("SeTakeOwnershipPrivilege") #Necessary to override FilePermissions
    }
    Process {
        ForEach ($Item in $Path) {
            Write-Verbose "FullName: $Item"
            #The ACL objects do not like being used more than once, so re-create them on the Process block
            $DirOwner = New-Object System.Security.AccessControl.DirectorySecurity
            $DirOwner.SetOwner([System.Security.Principal.NTAccount]$Account)
            $FileOwner = New-Object System.Security.AccessControl.FileSecurity
            $FileOwner.SetOwner([System.Security.Principal.NTAccount]$Account)
            $DirAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity
            $FileAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity
            $AdminACL = New-Object System.Security.AccessControl.FileSystemAccessRule('Builtin\Administrators','FullControl','ContainerInherit,ObjectInherit','InheritOnly','Allow')
            $FileAdminAcl.AddAccessRule($AdminACL)
            $DirAdminAcl.AddAccessRule($AdminACL)
            Try {
                $Item = Get-Item -LiteralPath $Item -Force -ErrorAction Stop
                If (-NOT $Item.PSIsContainer) {
                    If ($PSCmdlet.ShouldProcess($Item, 'Set File Owner')) {
                        Try {
                            $Item.SetAccessControl($FileOwner)
                        } Catch {
                            Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Directory.FullName)"
                            $Item.Directory.SetAccessControl($FileAdminAcl)
                            $Item.SetAccessControl($FileOwner)
                        }
                    }
                } Else {
                    If ($PSCmdlet.ShouldProcess($Item, 'Set Directory Owner')) {                        
                        Try {
                            $Item.SetAccessControl($DirOwner)
                        } Catch {
                            Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Parent.FullName)"
                            $Item.Parent.SetAccessControl($DirAdminAcl) 
                            $Item.SetAccessControl($DirOwner)
                        }
                    }
                    If ($Recurse) {
                        [void]$PSBoundParameters.Remove('Path')
                        Get-ChildItem $Item -Force | Set-Owner @PSBoundParameters
                    }
                }
            } Catch {
                Write-Warning "$($Item): $($_.Exception.Message)"
            }
        }
    }
    End {  
        #Remove priviledges that had been granted
        [void][TokenAdjuster]::RemovePrivilege("SeRestorePrivilege") 
        [void][TokenAdjuster]::RemovePrivilege("SeBackupPrivilege") 
        [void][TokenAdjuster]::RemovePrivilege("SeTakeOwnershipPrivilege")     
    }
}


#********************************************* function set-owner end

$setuproot = $testroot + $testfolderprefix #concatenated path for setup

#Creat directories and copy files and set security on file 2 in each folder
For ($i=1; $i -le 5; $i++) {

#Rootfolder setup
    $setupdir = $setuproot + $i
    md $setupdir
#file1
    $testfile1 = $setupdir + "\testfile1.png"
    copy $testfilesrc $testfile1
#file2
    $testfile2 = $setupdir + "\testfile2.png"
    copy $testfileSrc $testfile2
    #set restriction on file2, lock to guest fullcontrol and guest ownership
        $acl = get-acl $testfile2
        $acl.SetAccessRuleProtection($true,$false)
        $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($restrictaccount, "FullControl", "Allow")
        $Acl.SetAccessRule($Ar)
        Set-Acl $testfile2 $acl 
        Set-Owner $testfile2 -account $restrictaccount
#subfolder setup
    $setupsubdir = $setupdir + "\Subfolder"
    md $setupsubdir
#file1
    $testfile1sub = $setupsubdir + "\testfile1.png"
    copy $testfilesrc $testfile1sub
#file2
    $testfile2sub = $setupsubdir + "\testfile2.png"
    copy $testfileSrc $testfile2sub
    #set restriction on file2, lock to guest fullcontrol and guest ownership
        $acl = get-acl $testfile2sub
        $acl.SetAccessRuleProtection($true,$false)
        $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($restrictaccount, "FullControl", "Allow")
        $Acl.SetAccessRule($Ar)
        Set-Acl $testfile2sub $acl 
        Set-Owner $testfile2sub -account $restrictaccount

    }

# restrict folder access : 3 sub
$folder3sub  = $setuproot + "3\subfolder"
$acl = get-acl $folder3sub
$acl.SetAccessRuleProtection($true,$false)
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("guest", "FullControl", "ContainerInherit,ObjectInherit", "None", "allow")
$Acl.SetAccessRule($Ar)
Set-Acl $folder3sub $acl 
Set-Owner $folder3sub -account 'guest'


# restrict folder access : 4
$folder4  = $setuproot + "4"
$acl = get-acl $folder4
$acl.SetAccessRuleProtection($true,$false)
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("guest", "FullControl", "ContainerInherit,ObjectInherit", "None", "allow")
$Acl.SetAccessRule($Ar)
Set-Acl $folder4 $acl 
Set-Owner $folder4 -account 'guest'

# restrict folder access : 5 sub
$folder5sub  = $setuproot + "5\subfolder"
$acl = get-acl $folder5sub
$acl.SetAccessRuleProtection($true,$false)
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("guest", "FullControl", "ContainerInherit,ObjectInherit", "None", "allow")
$Acl.SetAccessRule($Ar)
Set-Acl $folder5sub $acl 
Set-Owner $folder5sub -account 'guest'

# restrict folder access : 5
$folder5  = $setuproot + "5"
$acl = get-acl $folder5
$acl.SetAccessRuleProtection($true,$false)
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("guest", "FullControl", "ContainerInherit,ObjectInherit", "None", "allow")
$Acl.SetAccessRule($Ar)
Set-Acl $folder5 $acl 
Set-Owner $folder5 -account 'guest'