From 680dc88899c5790ac056cef9134ddb87a82c4df9 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 12 Jun 2016 18:04:36 -0500 Subject: [PATCH] (GH-398) Explicitly Set Permissions Explicitly set ACEs for Chocolatey's default folder installation to Administrators, removing inherited permissions and ensuring container and object inheritance flow from explicit ACE settings. Only remove inheritance for the default install folder, if being installed elsewhere, leave inherited permissions alone. Additionally, only set the current user to have modify access if there is an environment variable set to allow this behavior - `$env:ChocolateyInstallAllowCurrentUser="true"`. Based on conversations and code examples from @jberezanski. Jakub wrote the Get-LocalizedWellKnownPrincipalName to return the localized user name for Well-Known SIDS. --- nuget/chocolatey/tools/chocolateysetup.psm1 | 74 +++++++++++++++++---- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/nuget/chocolatey/tools/chocolateysetup.psm1 b/nuget/chocolatey/tools/chocolateysetup.psm1 index 52f9d9ea75..b91c94ee6a 100644 --- a/nuget/chocolatey/tools/chocolateysetup.psm1 +++ b/nuget/chocolatey/tools/chocolateysetup.psm1 @@ -174,6 +174,18 @@ function Create-DirectoryIfNotExists($folderName){ if (![System.IO.Directory]::Exists($folderName)) { [System.IO.Directory]::CreateDirectory($folderName) | Out-Null } } +function Get-LocalizedWellKnownPrincipalName { +param ( + [Parameter(Mandatory = $true)] + [Security.Principal.WellKnownSidType] $WellKnownSidType +) + $sid = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList @($WellKnownSidType, $null) + $account = $sid.Translate([Security.Principal.NTAccount]) + + return $account.Value +} + + function Ensure-UserPermissions { param( [string]$folder @@ -181,29 +193,67 @@ param( Write-Debug "Ensure-UserPermissions" if (!(Test-ProcessAdminRights)) { - Write-ChocolateyWarning "User is not running elevated, cannot set user permissions." + Write-ChocolateyWarning "User is not running elevated, cannot set permissions." return } $currentEA = $ErrorActionPreference $ErrorActionPreference = 'Stop' try { - # get current user - $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() # get current acl - $acl = Get-Acl $folder + $acl = (Get-Item $folder).GetAccessControl('Access') + + $inheritanceFlags = ([Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [Security.AccessControl.InheritanceFlags]::ObjectInherit) + $propagationFlags = [Security.AccessControl.PropagationFlags]::None + + $rightsFullControl = [Security.AccessControl.FileSystemRights]::FullControl + $rightsModify = [Security.AccessControl.FileSystemRights]::Modify + $rightsReadExecute = [Security.AccessControl.FileSystemRights]::ReadAndExecute + + Write-Output "Restricting write permissions to Administrators" + $builtinAdmins = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid) + $adminsAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinAdmins, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow") + $acl.SetAccessRule($adminsAccessRule) + $localSystem = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::LocalSystemSid) + $localSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($localSystem, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow") + $acl.SetAccessRule($localSystemAccessRule) + $builtinUsers = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinUsersSid) + $usersAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinUsers, $rightsReadExecute, $inheritanceFlags, $propagationFlags, "Allow") + $acl.SetAccessRule($usersAccessRule) + + $allowCurrentUser = $env:ChocolateyInstallAllowCurrentUser -eq 'true' + if ($allowCurrentUser) { + # get current user + $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() + + if ($currentUser.Name -ne $localSystem) { + $userAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($currentUser.Name, $rightsModify, $inheritanceFlags, $propagationFlags, "Allow") + Write-ChocolateyWarning 'Adding Modify permission for current user due to $env:ChocolateyInstallAllowCurrentUser' + $acl.SetAccessRule($userAccessRule) + } + } else { + Write-Debug 'Current user no longer set due to possible escalation of privileges - set $env:ChocolateyInstallAllowCurrentUser="true" if you require this.' + } + + $defaultInstallPath = "$env:SystemDrive\ProgramData\chocolatey" + try { + $defaultInstallPath = Join-Path [Environment]::GetFolderPath("CommonApplicationData") 'chocolatey' + } catch { + # keep first setting + } - # define rule to set - $rights = "Modify" - $userAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($currentUser.Name, $rights, "Allow") + if ($folder.ToLower() -eq $defaultInstallPath.ToLower()) { + Write-Debug "Default Installation folder - removing inheritance with no copy" + $acl.SetAccessRuleProtection($true, $false) + } else { + Write-Debug "Non-standard install location - leaving inheritance on" + $acl.SetAccessRuleProtection($false, $true) + } # this is idempotent - Write-Output "Adding Modify permission for current user to '$folder'" - $acl.SetAccessRuleProtection($false,$true) - $acl.SetAccessRule($userAccessRule) - Set-Acl $folder $acl + (Get-Item $folder).SetAccessControl($acl) } catch { - Write-ChocolateyWarning "Not able to set permissions for user." + Write-ChocolateyWarning "Not able to set permissions for $folder." } $ErrorActionPreference = $currentEA }