diff --git a/src/System.Management.Automation/engine/PropertyAccessor.cs b/src/System.Management.Automation/engine/PropertyAccessor.cs index 7cdd7e3bbd..6e18c6a64a 100644 --- a/src/System.Management.Automation/engine/PropertyAccessor.cs +++ b/src/System.Management.Automation/engine/PropertyAccessor.cs @@ -146,7 +146,7 @@ namespace System.Management.Automation // // Sets the per-user configuration directory // - appDataConfigDirectory = Utils.GetUserSettingsDirectory(); + appDataConfigDirectory = Utils.GetUserConfigurationDirectory(); if (!Directory.Exists(appDataConfigDirectory)) { try @@ -166,11 +166,11 @@ namespace System.Management.Automation /// not interfere with PowerShell initialization /// /// Returns the directory if present or creatable. Throws otherwise. - private string GetAppDataConfigDirectory() + private string GetCurrentUserConfigDirectory() { if (null == appDataConfigDirectory) { - string tempAppDataConfigDir = Utils.GetUserSettingsDirectory(); + string tempAppDataConfigDir = Utils.GetUserConfigurationDirectory(); if (!Directory.Exists(tempAppDataConfigDir)) { Directory.CreateDirectory(tempAppDataConfigDir); @@ -194,7 +194,7 @@ namespace System.Management.Automation // Defaults to system wide. if (PropertyScope.CurrentUser == scope) { - scopeDirectory = GetAppDataConfigDirectory(); + scopeDirectory = GetCurrentUserConfigDirectory(); } string fileName = Path.Combine(scopeDirectory, configFileName); @@ -229,7 +229,7 @@ namespace System.Management.Automation // Defaults to system wide. if(PropertyScope.CurrentUser == scope) { - scopeDirectory = GetAppDataConfigDirectory(); + scopeDirectory = GetCurrentUserConfigDirectory(); } string fileName = Path.Combine(scopeDirectory, configFileName); @@ -250,7 +250,7 @@ namespace System.Management.Automation // Defaults to system wide. if (PropertyScope.CurrentUser == scope) { - scopeDirectory = GetAppDataConfigDirectory(); + scopeDirectory = GetCurrentUserConfigDirectory(); } string fileName = Path.Combine(scopeDirectory, configFileName); @@ -265,7 +265,7 @@ namespace System.Management.Automation // Defaults to system wide. if (PropertyScope.CurrentUser == scope) { - scopeDirectory = GetAppDataConfigDirectory(); + scopeDirectory = GetCurrentUserConfigDirectory(); } string fileName = Path.Combine(scopeDirectory, configFileName); diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs index 63c687050f..7f38adcf9e 100644 --- a/src/System.Management.Automation/engine/Utils.cs +++ b/src/System.Management.Automation/engine/Utils.cs @@ -282,16 +282,16 @@ namespace System.Management.Automation /// /// Specifies the per-user configuration settings directory in a platform agnostic manner. - /// Windows Ex: - /// %LOCALAPPDATA%\PowerShell - /// Non-Windows Ex: - /// ~/.config/PowerShell /// /// The current user's configuration settings directory - internal static string GetUserSettingsDirectory() + internal static string GetUserConfigurationDirectory() { - string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - return Path.Combine(appDataPath, "PowerShell"); +#if UNIX + return Platform.SelectProductNameForDirectory(Platform.XDG_Type.CONFIG); +#else + string basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + return IO.Path.Combine(basePath, Utils.ProductNameForDirectory); +#endif } private static string[] GetProductFolderDirectories() diff --git a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs index 324a1d7ea2..524ff7172c 100644 --- a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs +++ b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs @@ -182,12 +182,7 @@ namespace System.Management.Automation if (forCurrentUser) { -#if UNIX - basePath = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CONFIG); -#else - basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); - basePath = IO.Path.Combine(basePath, Utils.ProductNameForDirectory); -#endif + basePath = Utils.GetUserConfigurationDirectory(); } else { diff --git a/test/powershell/engine/ExecutionPolicy.Tests.ps1 b/test/powershell/engine/ExecutionPolicy.Tests.ps1 index d829393c46..ed2cd0670c 100644 --- a/test/powershell/engine/ExecutionPolicy.Tests.ps1 +++ b/test/powershell/engine/ExecutionPolicy.Tests.ps1 @@ -851,6 +851,99 @@ ZoneId=$FileType } } +Describe "Validate Set-ExecutionPolicy -Scope" -Tags "CI" { + + BeforeAll { + $originalPolicies = Get-ExecutionPolicy -list + + # Calls Set-ExecutionPolicy with a known-bad Scope and expects failure. + # It is defined here so that it will be available at It scope. + function VerfiyBlockedSetExecutionPolicy + { + param( + [string] + $policyScope + ) + $fqeid = "" + try { + Set-ExecutionPolicy -Scope $policyScope -ExecutionPolicy Restricted + } + catch { + $fqeid = $_.FullyQualifiedErrorId + } + + $fqeid | Should Be "CantSetGroupPolicy,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand" + } + } + + AfterAll { + foreach ($scopedPolicy in $originalPolicies) + { + if (($scopedPolicy.Scope -eq "Process") -or + ($scopedPolicy.Scope -eq "CurrentUser")) + { + try { + Set-ExecutionPolicy -Scope $scopedPolicy.Scope -ExecutionPolicy $scopedPolicy.ExecutionPolicy -Force + } + catch { + if ($_.FullyQualifiedErrorId -ne "ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand") + { + # Re-throw unrecognized exceptions. Otherwise, swallow + # the exception that warns about overridden policies + throw $_ + } + } + } + elseif($scopedPolicy.Scope -eq "LocalMachine") + { + try { + Set-ExecutionPolicy -Scope $scopedPolicy.Scope -ExecutionPolicy $scopedPolicy.ExecutionPolicy -Force + } + catch { + if ($_.FullyQualifiedErrorId -eq "System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand") + { + # Do nothing. Depending on the ownership of the file, + # regular users may or may not be able to set its + # value. + # + # When targetting the Registry, regular users cannot + # modify this value. + } + elseif ($_.FullyQualifiedErrorId -ne "ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand") + { + # Re-throw unrecognized exceptions. Otherwise, swallow + # the exception that warns about overridden policies + throw $_ + } + } + } + } + } + + It "-Scope MachinePolicy is not Modifiable" { + VerfiyBlockedSetExecutionPolicy "MachinePolicy" + } + + It "-Scope UserPolicy is not Modifiable" { + VerfiyBlockedSetExecutionPolicy "UserPolicy" + } + + It "-Scope Process is Settable" { + Set-ExecutionPolicy -Scope Process -ExecutionPolicy ByPass + Get-ExecutionPolicy -Scope Process | Should Be "ByPass" + } + + It "-Scope CurrentUser is Settable" { + Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy ByPass + Get-ExecutionPolicy -Scope CurrentUser | Should Be "ByPass" + } + + # This test requires Administrator privileges on Windows. + It "-Scope LocalMachine is Settable" { + Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy ByPass + Get-ExecutionPolicy -Scope LocalMachine | Should Be "ByPass" + } +} Describe "Validate that 'ConvertTo-SecureString -Key' and 'ConvertFrom-SecureString -Key' work on NanoServer and IoT" -Tags "CI" {