Reputation: 1721
I have a Powershell script which changes a registry value that is usually owned by TrustedInstaller. The basic workflow is:
Try to open the key for editing
If this fails, try to open the key for permissions
if ($backupAcl -eq $null) { $backupAcl = $key.GetAccessControl(); }
$acl = $key.GetAccessControl();
$acl.SetOwner($me);
Backup the ACL with if ($backupAcl -eq $null) { $backupAcl = $key.GetAccessControl(); }
$acl = $key.GetAccessControl();
$acl.AddAccessRule($rule); $acl.SetAccessControl($acl);
Change the values I need to change with $key.SetValue(...)
Revert any changes to permissions made earlier.
The code I am using to revert the permissions is as follows:
$key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);
Write-Host "Setting permissions to:"
Format-List -InputObject $aclBackup;
$key.SetAccessControl($aclBackup);
Write-Host "Permissions set to:"
Format-List -InputObject $key.GetAccessControl();
$key.Close();
...however, it never actually sets the ACL back to what it was.
Other than this, the script works fine -- the ACL is set to what it needs to be to change the values (so I know I can change the ACL) and the values themselves are changed (so I know I have changed the ACL).
But the reversion never takes. No exceptions are raised -- it just never takes.
Why not? And how can I revert the ACL to what it was when the script started?
Upvotes: 2
Views: 1993
Reputation: 1721
I got it. It seems you cannot re-use ObjectSecurity
objects in this fashion, so I had to serialize the backup ACL using the GetSecurityDescriptorBinaryForm()
method and deserialize it back again using the SetSecurityDescriptorBinaryForm(...)
method.
Once I had done that, though, I got another error - The security identifier is not allowed to be the owner of this object.
I had to overcome this by requesting the SeRestorePrivilege
system privilege, which I did with the Enable-Privelege
function from http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/e718a560-2908-4b91-ad42-d392e7f8f1ad (a function I was already using to request the SeTakeOwnershipPrivilege
needed to take ownership in the first place).
Once I had this privilege, I could overwrite the ACL with the deserialized one I had in my cache.
So, to backup the ACL:
if ($aclBackup -eq $null) {
$aclBackup = $key.GetAccessControl().GetSecurityDescriptorBinaryForm();
}
And to restore it:
if (Enable-Privilege SeRestorePrivilege) {
$acl = New-Object System.Security.AccessControl.RegistrySecurity;
$acl.SetSecurityDescriptorBinaryForm($aclBackup, $aclIncludeAll);
$key = $keyRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);
$key.SetAccessControl($acl);
$key.Close();
}
Hopes this helps someone else in the future...
Upvotes: 1
Reputation: 1550
Since you're making modifications to an object in memory you will need to use the command Set-ACL
to effect the change down to the actual file ACL.
Using Get ACL will read the access list from a registry key. I do not think you need this line.
$key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);
Try
$ACLobject = Get-ACL -Path $RegKey
$ACLObject |Set-ACL -Path $newRegKey
In between that you can manipulate the properties of $ACLobject any way you like.
Upvotes: 0