Fix Issue #20553 #15737 - merge with reg functionality #19443 (#20555)

This commit is contained in:
JimFicarra 2017-03-06 15:56:17 -05:00 committed by Matt Davis
parent 66489b233e
commit 2206b5e900

View file

@ -108,7 +108,110 @@ Function UserSearch
} }
} }
} }
# Need to adjust token privs when executing Set-ACL in certain cases.
# e.g. d:\testdir is owned by group in which current user is not a member and no perms are inherited from d:\
# This also sets us up for setting the owner as a feature.
$AdjustTokenPrivileges = @"
using System;
using System.Runtime.InteropServices;
namespace Ansible {
public class TokenManipulator {
[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
Function SetPrivilegeTokens() {
# Set privilege tokens only if admin.
# Admins would have these privs or be able to set these privs in the UI Anyway
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
if ($myWindowsPrincipal.IsInRole($adminRole)) {
# See the following for details of each privilege
# https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx
[void][Ansible.TokenManipulator]::AddPrivilege("SeRestorePrivilege") #Grants all write access control to any file, regardless of ACL.
[void][Ansible.TokenManipulator]::AddPrivilege("SeBackupPrivilege") #Grants all read access control to any file, regardless of ACL.
[void][Ansible.TokenManipulator]::AddPrivilege("SeTakeOwnershipPrivilege") #Grants ability to take owernship of an object w/out being granted discretionary access
}
}
$params = Parse-Args $args; $params = Parse-Args $args;
$result = New-Object PSObject; $result = New-Object PSObject;
@ -141,14 +244,18 @@ If (Test-Path -Path $path -PathType Leaf) {
ElseIf ($inherit -eq "") { ElseIf ($inherit -eq "") {
$inherit = "ContainerInherit, ObjectInherit" $inherit = "ContainerInherit, ObjectInherit"
} }
$ErrorActionPreference = "Stop"
Try { Try {
SetPrivilegeTokens
If ($path -match "^HK(CC|CR|CU|LM|U):\\") { If ($path -match "^HK(CC|CR|CU|LM|U):\\") {
$colRights = [System.Security.AccessControl.RegistryRights]$rights $colRights = [System.Security.AccessControl.RegistryRights]$rights
} }
Else { Else {
$colRights = [System.Security.AccessControl.FileSystemRights]$rights $colRights = [System.Security.AccessControl.FileSystemRights]$rights
} }
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]$inherit $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]$inherit
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]$propagation $PropagationFlag = [System.Security.AccessControl.PropagationFlags]$propagation
@ -161,32 +268,46 @@ Try {
$objUser = New-Object System.Security.Principal.SecurityIdentifier($sid) $objUser = New-Object System.Security.Principal.SecurityIdentifier($sid)
If ($path -match "^HK(CC|CR|CU|LM|U):\\") { If ($path -match "^HK(CC|CR|CU|LM|U):\\") {
$objACE = New-Object System.Security.AccessControl.RegistryAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType) $objACE = New-Object System.Security.AccessControl.RegistryAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
} }
Else { Else {
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType) $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
} }
$objACL = Get-ACL $path $objACL = Get-ACL $path
# Check if the ACE exists already in the objects ACL list # Check if the ACE exists already in the objects ACL list
$match = $false $match = $false
If ($path -match "^HK(CC|CR|CU|LM|U):\\") { If ($path -match "^HK(CC|CR|CU|LM|U):\\") {
ForEach($rule in $objACL.Access){ ForEach($rule in $objACL.Access){
$ruleIdentity = $rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) $ruleIdentity = $rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])
If (($rule.RegistryRights -eq $objACE.RegistryRights) -And ($rule.AccessControlType -eq $objACE.AccessControlType) -And ($ruleIdentity -eq $objACE.IdentityReference) -And ($rule.IsInherited -eq $objACE.IsInherited) -And ($rule.InheritanceFlags -eq $objACE.InheritanceFlags) -And ($rule.PropagationFlags -eq $objACE.PropagationFlags)) { If (($rule.RegistryRights -eq $objACE.RegistryRights) -And ($rule.AccessControlType -eq $objACE.AccessControlType) -And ($ruleIdentity -eq $objACE.IdentityReference) -And ($rule.IsInherited -eq $objACE.IsInherited) -And ($rule.InheritanceFlags -eq $objACE.InheritanceFlags) -And ($rule.PropagationFlags -eq $objACE.PropagationFlags)) {
$match = $true $match = $true
Break Break
}
} }
} }
}
Else { Else {
ForEach($rule in $objACL.Access){ # Workaround to handle special use case 'APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES' and
$ruleIdentity = $rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) # 'APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES'- can't translate fully qualified name (win32 API bug/oddity)
If (($rule.FileSystemRights -eq $objACE.FileSystemRights) -And ($rule.AccessControlType -eq $objACE.AccessControlType) -And ($ruleIdentity -eq $objACE.IdentityReference) -And ($rule.IsInherited -eq $objACE.IsInherited) -And ($rule.InheritanceFlags -eq $objACE.InheritanceFlags) -And ($rule.PropagationFlags -eq $objACE.PropagationFlags)) { # 'ALL APPLICATION PACKAGES' exists only on Win2k12 and Win2k16 and 'ALL RESTRICTED APPLICATION PACKAGES' exists only in Win2k16
$match = $true
Break $specialIdRefs = "ALL APPLICATION PACKAGES","ALL RESTRICTED APPLICATION PACKAGES"
}
} ForEach($rule in $objACL.Access){
$idRefShortValue = ($rule.IdentityReference.Value).split('\')[-1]
if ( $idRefShortValue -in $specialIdRefs ) {
$ruleIdentity = (New-Object Security.Principal.NTAccount $idRefShortValue).Translate([Security.Principal.SecurityIdentifier])
}
else {
$ruleIdentity = $rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])
}
If (($rule.FileSystemRights -eq $objACE.FileSystemRights) -And ($rule.AccessControlType -eq $objACE.AccessControlType) -And ($ruleIdentity -eq $objACE.IdentityReference) -And ($rule.IsInherited -eq $objACE.IsInherited) -And ($rule.InheritanceFlags -eq $objACE.InheritanceFlags) -And ($rule.PropagationFlags -eq $objACE.PropagationFlags)) {
$match = $true
Break
}
}
} }
If ($state -eq "present" -And $match -eq $false) { If ($state -eq "present" -And $match -eq $false) {
@ -196,7 +317,7 @@ Try {
Set-Attr $result "changed" $true; Set-Attr $result "changed" $true;
} }
Catch { Catch {
Fail-Json $result "an exception occurred when adding the specified rule" Fail-Json $result "an exception occurred when adding the specified rule - $($_.Exception.Message)"
} }
} }
ElseIf ($state -eq "absent" -And $match -eq $true) { ElseIf ($state -eq "absent" -And $match -eq $true) {
@ -206,7 +327,7 @@ Try {
Set-Attr $result "changed" $true; Set-Attr $result "changed" $true;
} }
Catch { Catch {
Fail-Json $result "an exception occurred when removing the specified rule" Fail-Json $result "an exception occurred when removing the specified rule - $($_.Exception.Message)"
} }
} }
Else { Else {
@ -221,7 +342,7 @@ Try {
} }
} }
Catch { Catch {
Fail-Json $result "an error occurred when attempting to $state $rights permission(s) on $path for $user" Fail-Json $result "an error occurred when attempting to $state $rights permission(s) on $path for $user - $($_.Exception.Message)"
} }
Exit-Json $result Exit-Json $result