An interesting question came up on SuperUser the other day. The OP wanted to know how to change the account of a NTFS ACL but still retain all of the ACL settings (privileges, inheritance etc.…). This could be needed if the original account was deleted, or if the ACL was on a drive that was moved to another machine etc.…
When the ACL entry has an unresolvable account it will appear like this:
The first thing that came to mind was to edit the SDDL string. The SDDL is a not so easy to read string representation of the ACL. It looks like this:
Easy to read huh?
You can learn all about the format on MSDN, however the format is not important for our purpose here. All we need to do is replace the SID with the SID of the account we want.
So first lets use the Win32_Account WMI class to get a list of user account SIDs:
This will get all account types from the local machine and the domain if the machine is on a domain which could make this command take a really long time.
To make it go faster we’ll filter the query a little bit. There are a couple properties of this class we can use to reduce the run time.
So to get the SID of a local user account named NewAccount we’ll use:
To find the SID of the broken ACL entry we’ll use the Get-ACL cmdlet. The ACE’s are stored in the Access property returned by the Get-Acl object. To retrieve the SID of the entry which account is unknown we’ll use the Translate method to find that one that can’t translate to an NTAccount object. We also aren’t interested in ACE’s that are inherited so we’ll filter them out.
The invalid SIDs are stored in the array $invalidSids.
Now we can do a simple string search and replace in the SDDL string.
The last step is to set the ACL with the updated SDDL. To do this we’ll use the SetSecurityDescriptorSddlForm method.
And that’s it. The ACL is now updated with the account but all of the previous ACE settings are retained as we wanted.