PowerShell: Manipulating & Copying File Permissions In Windows

The Mystery

Recently a folder within a SMB share on the Windows Server (network share) displayed only certain files but not others for a certain user. For an administrator, the share displayed all the files in the folder. Obviously, there is some difference in the permissions, but what? Examining the difference between the files (using “Right-click -> Properties -> Security”) that were visible vs. invisible revealed that some AD groups were granted permissions on the visible one but not on the invisible files. I just had to copy the permissions of the good one to the others to fix the issue.

NTFS vs. and SMB share permissions:

There is a difference between setting NTFS permissions on the folder and setting permissions on the SMB share (two separate UI tabs in File Explorer). They do interact with each other though. Simply know that “the most restrictive permission wins” if there is an overlap between the NTFS and SMB share permissions. Here is a nice reference on the differences and the interaction: 

https://www.varonis.com/blog/ntfs-permissions-vs-share/

Notice that there only three types of permissions for the share whereas there is so much more control of permissions for the folder.

To avoid confusion and for clarity, I generally match the folder permissions and the SMB share permissions. 

NTFS PermissionsSMB Share Permissions
Right-click Folder -> Properties -> Security ..Right-click Folder -> Share -> Share ..
Get permissions on folder:
(Get-Acl "D:\SharedFolder").Access
List SMB Shares on the host:
Get-SmbShare

Get a SMB share’s permissions:
Get-SmbShareAccess MySMBShareName

Set a SMB share’s permissions (on creation):
New-SmbShare `
    -Description "Share Description" `
    -Name "ShareName" `
    -Path "F:\ShareInDrive" `
    -ReadAccess 'MyFirm\FinanceGroup' `
    -FullAccess @('MyFirm\ManufacturingGroup', 
         'MyFirm\SalesGroup') 

NTFS Folder Permissions vs SMB Share Permissions

Having said that you can either set the permission on the share and match it to the folder or vice versa. However, there is a command that overwrites folder permissions with the share permissions – Set-SMBPathAcl

#Sets the ACL for the file system folder to match the ACL used by an SMB share.
#Below ShareName is one of the names that you get from Get-SmbShare command

Set-SmbPathAcl -ShareName MyShare

This way, if you set the share permissions and test it, you can force that on the folder.

Setting file permissions manually:

I could have set the correct permissions at the folder level and could have applied it to all the files within the folder by going to Properties -> Security -> Advanced and checked the “Replace all child object permission entries with inheritable permission entries from this object” and hit “OK”.

While it is easy, this method will not allow for finer control if the security has to be different between the files in the folder.

Copying one file’s permissions to another:

Let us say ModelFile.txt has the right permissions and MessedUpFile.txt had certain permissions missing. The easiest way to copy the permissions from the former to the latter is using the PowerShell *ACL* (Access Control List) commands.

#Get the Access Control List (ACL) from the good file
$acl = Get-Acl "D:\SharedFolder\ModelFile.txt"

#Apply the permissions to the messed-up file
$acl | Set-Acl "D:\SharedFolder\MessedUpFile.txt"

That was easy, right? When you look at the $acl.Access value, it might look like this:

Access Control List

Changing permissions for entire folder/subfolder

Now, let us say we want apply the permissions to all the other files in the folder, you just set the ideal permissions in a file such as ModelFile.txt and get and apply its ACL to all the files.

#Get the Access Control List (ACL) from the good file
$acl = Get-Acl "D:\SharedFolder\ModelFile.txt"

#Apply the permissions to all the files in the folder and sub-folders
Get-ChildItem `
    -Path "D:\SharedFolder" `
    -Recurse `
    -Include "*.*" `
    -Force | 
Set-Acl `
    -AclObject $acl

If you do not want to do this in the sub-folders, just take out the “Recurse” parameter. Also, if you wanted to do it for just certain file-types, change what you want to by altering the “Include” parameter to say “*.mdb”.

Adding additional permissions to ACL

Ideally, you set permissions on a model file and apply it to the rest. There may be cases where it is not so black and white. Let us say some files need certain permissions added based on the type. Pretend that we need to add grant full-control to these 3 users/groups to all “.mdb” files

$acl = Get-Acl "F:\SQLData\ModelFile.txt"

$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
                    'MyDomain\FinanceGroup',"FullControl","Allow")
$acl.AddAccessRule($AccessRule)

$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
                    'MyDomain\HRGroup',"FullControl","Allow")
$acl.AddAccessRule($AccessRule)

$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
                    'MSSQLServer',"FullControl","Allow")
$acl.AddAccessRule($AccessRule)

#Apply the permissions to all the .mdb files in the folder
Get-ChildItem `
    -Path "D:\SharedFolder" `
    -Include "*.mdb" `
    -Force | 
Set-Acl `
    -AclObject $acl

Notice how we used System.Security.AccessControl.FileSystemAccessRule to add the permissions we needed.

We could have done it more elegantly like this:

$AccessRule = New-Object 
   System.Security.AccessControl.FileSystemAccessRule(
   'MSSQLServer', 
   [System.Security.AccessControl.FileSystemRights]::FullControl,
   [System.Security.AccessControl.AccessControlType]::Allow)

The available constants:

There are constants that correspond to the to boxed things – Allow/Deny option and the permission types.

[System.Security.AccessControl.AccessControlType] Enum has these constants (again copied from linked MS documentation). In PowerShell just type :: (colon, colon) after [System.Security.AccessControl.AccessControlType] and check the list.

Allow0The AccessRule object is used to allow access to a secured object.
Deny1The AccessRule object is used to deny access to a secured object.

[System.Security.AccessControl.FileSystemRights] Enum has these values (copied from linked MS documentation). In PowerShell just type :: (colon, colon) after [System.Security.AccessControl.FileSystemRights] and check the list.

AppendData4Specifies the right to append data to the end of a file.
ChangePermissions262144Specifies the right to change the security and audit rules associated with a file or folder.
CreateDirectories4Specifies the right to create a folder This right requires the Synchronize value.
CreateFiles2Specifies the right to create a file. This right requires the Synchronize value.
Delete65536Specifies the right to delete a folder or file.
DeleteSubdirectoriesAndFiles64Specifies the right to delete a folder and any files contained within that folder.
ExecuteFile32Specifies the right to run an application file.
FullControl2032127Specifies the right to exert full control over a folder or file, and to modify access control and audit rules. This value represents the right to do anything with a file and is the combination of all rights in this enumeration.
ListDirectory1Specifies the right to read the contents of a directory.
Modify197055Specifies the right to read, write, list folder contents, delete folders and files, and run application files. This right includes the ReadAndExecute right, the Write right, and the Delete right.
Read131209Specifies the right to open and copy folders or files as read-only. This right includes the ReadData right, ReadExtendedAttributes right, ReadAttributes right, and ReadPermissions right.
ReadAndExecute131241Specifies the right to open and copy folders or files as read-only, and to run application files. This right includes the Read right and the ExecuteFile right.
ReadAttributes128Specifies the right to open and copy file system attributes from a folder or file. For example, this value specifies the right to view the file creation or modified date. This does not include the right to read data, extended file system attributes, or access and audit rules.
ReadData1Specifies the right to open and copy a file or folder. This does not include the right to read file system attributes, extended file system attributes, or access and audit rules.
ReadExtendedAttributes8Specifies the right to open and copy extended file system attributes from a folder or file. For example, this value specifies the right to view author and content information. This does not include the right to read data, file system attributes, or access and audit rules.
ReadPermissions131072Specifies the right to open and copy access and audit rules from a folder or file. This does not include the right to read data, file system attributes, and extended file system attributes.
Synchronize1048576Specifies whether the application can wait for a file handle to synchronize with the completion of an I/O operation. This value is automatically set when allowing access and automatically excluded when denying access.
TakeOwnership524288Specifies the right to change the owner of a folder or file. Note that owners of a resource have full access to that resource.
Traverse32Specifies the right to list the contents of a folder and to run applications contained within that folder.
Write278Specifies the right to create folders and files, and to add or remove data from files. This right includes the WriteData right, AppendData right, WriteExtendedAttributes right, and WriteAttributes right.
WriteAttributes256Specifies the right to open and write file system attributes to a folder or file. This does not include the ability to write data, extended attributes, or access and audit rules.
WriteData2Specifies the right to open and write to a file or folder. This does not include the right to open and write file system attributes, extended file system attributes, or access and audit rules.
WriteExtendedAttributes16Specifies the right to open and write extended file system attributes to a folder or file. This does not include the ability to write data, attributes, or access and audit rules.

Create SMB shares and copy permissions – Example

This is not anything you may use as is but am including it so that you can see how I do the following

  1. List volumes on the computer
  2. Shows the shares and allows selection of shares to remove
  3. Loops through and creates shares like another host
  4. Copies the permissions
  5. Revokes permissions for “Everyone” that is there by default
  6. Copies the folder structures (without the files) to target
# Script is to be run on the target host
# The goal of this script is to create shares just like SomeHostNas01 on SomeHostNas02
#   and copy the permisisons from 01 to 02 at the root folder level
#   plus copy all the folder structures from the source to the target
#
# Example
#   On the source, the shares run from 0 thru 7
#     \\SomeHostNas01\Share0 to \\SomeHostNas01\Share7
#   and we would like to create shares, copy permissions on target
#     \\SomeHostNas02\Share0 to \\SomeHostNas01\Share2
#
#  Warning: It will prompt for the shares to be dropped for recreation 
#            You can uncomment that portion to really drop and recreate
$source = "SomeHostNas01"
$target = "SomeHostNas02"

#If this is not running on the target, let us stop
if (($env:COMPUTERNAME -ne $target) -or  `
     ($source -eq $target))
{
    throw "You big dummy!! Watch what your'e doing!"
    exit
}

#List the volumes on the host
get-ciminstance -class win32_volume | select-object label, blocksize | format-table -autosize

#Get the list of shares currently on the commputer
Get-SmbShare *Share* 

#Uncomment to drop the shares - CAREFUL when re-running 
#.... You need to select the shares you want to remove in the GridView
#
#Get-SmbShare *Share* | 
#    Out-GridView -PassThru -Title "Select shares to remove" | 
#    Remove-SmbShare

#Shares are from 0 through 7 in the form EverestBackupStripe0 to EverestBackupStripe7
ForEach ($counter in @(0..7))
{
    New-SmbShare `
        -Description "Share$counter" `
        -Name "Share$counter" `
        -Path "F:\Share$counter" `
        -ReadAccess 'MyFirm\FinanceGroup' `
        -FullAccess @('MyFirm\ManufacturingGroup', 'MyFirm\SalesGroup')

    #Get the ACL from the source
    $acl = Get-Acl "\\$source\Share$counter"

    #Apply it to the target share
    $acl | 
        Set-Acl -Path "F:\Share$counter"

    #Check the permissions currently granted to the SMB share
    #Get-SmbShareAccess -Name Share$counter

    #Revoke the permissionf for "Everyone"
    Revoke-SmbShareAccess `
        -Name "Share$counter" `
        -AccountName Everyone `
        -Force    

    #Copy the folder structures from source to target
    Invoke-Expression "xcopy \\$source\Share$counter \\$target\Share$counter /t /e"
}

Conclusion:

File permissions are very complex especially if you get into the advanced options like inheritance and propagation flags. I am not an expert in this. If you were wondering how overlapping permissions work themselves out just remember that “Deny” permissions take precedence over “Allow” permissions.

Here are some good references that have better coverage with other usage examples:

One thought on “PowerShell: Manipulating & Copying File Permissions In Windows

Leave a comment