I have been spending a few hours working on a permission configuration issue on remote Windows systems (NT4, 2000 and 2003). The aim of my script was to modify the existing permission on a file on remote systems, as well as setting the ownership for this same file. Obviously I decided to use the cmdlet that Powershell kindly offers (gcm -noun acl), but there are only two:
CommandType Name ----------- ---- Cmdlet Get-Acl Cmdlet Set-Acl
At first sight I was sure that I was going to have problems with setting file ownership on a remote system because none of these two commands reference it. And I was right. Powershell doesn't allow to change file ownership on a remote file system (as explained here). I even tried to perform this operation with cacls and icacls, but I had no better luck and lot of errors (such as "no SID for trustee" and "Error Bad trustee name/SID no lookup").
As I do most of the times when I want to run something remotely and it doesn't work with native tools/cmdlets, I pulled from my magic hat the old good 'psexec.exe' in conjunction with 'filelacl.exe' (whose project has been recently abandoned by Microsoft, as you can see here, so hurry-up and store a copy of this program in safe place!).
My final script is a combination of pure Powershell cmdlets and freshly-mixed psexec and fileacl statements:
$remotehost = "test_host" $username1 = "my_username" $paswd = "my password" $path = "\\$remotehost\c$\folder\file.txt" $acl = Get-Acl $path #Going to add my username with Full Control $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$username1","FullControl","Allow") $acl.AddAccessRule($rule) #Going to assing readandexecute ot Everyone group $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("everyone","readandexecute","Allow") $acl.AddAccessRule($rule) #Going to remove permissions for the local Administrator group $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("administrators","FullControl","Allow") $acl.RemoveAccessRule($rule) Set-Acl $path $acl #Going to set the remote owner for this file psexec -c -u $username1 -p $paswd \\$remotehost fileacl.exe "$path" /O "$username1" #Let's check everything's been properly set Get-Acl $path | Format-List
I know it doesn't look good but that's the best I could do to solve my issue. It works this way:
- first of all I define a few variables, as the remote host name on which to work
- I retrieve the current ACL of the remote file
- I add two access rule: one for my username and one for the Everyone group
- I also add another access rule to remove the permission for the local admin group
- I apply these access rule with Set-Acl
- I start a psexec session on the remote host and fire fileacl to set the ownership
- I dump the applied permissions with Get-Acl to check everything went well
Possible values for rights that you can assign under System.Security.AccessControl.FileSystemAccessRule are listed below. Just choose the one that applies to your situation:
I hope this simple script will be useful for those who, like me, didn't find a way to write file ownership on remote Master File Tables... be it under Windows NT, Windows 2000 or Windows 2003. Maybe the Scripting Guy can intervene and post a better solution!