Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
wldpNativeMethods.cs873 linesDownload Raw Back to security
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4//5//  Application white listing policies such as AppLocker and DeviceGuard UMCI are only implemented on Windows OSs6//7#if !UNIX8 9using System.Diagnostics;10using System.Diagnostics.CodeAnalysis;11using System.Management.Automation.Internal;12using System.Management.Automation.Runspaces;13using System.Management.Automation.Tracing;14using System.Runtime.InteropServices;15 16namespace System.Management.Automation.Security17{18    /// <summary>19    /// System wide policy enforcement for a specific script file.20    /// </summary>21    public enum SystemScriptFileEnforcement22    {23        /// <summary>24        /// No policy enforcement.25        /// </summary>26        None = 0,27 28        /// <summary>29        /// Script file is blocked from running.30        /// </summary>31        Block = 1,32 33        /// <summary>34        /// Script file is allowed to run without restrictions (FullLanguage mode).35        /// </summary>36        Allow = 2,37 38        /// <summary>39        /// Script file is allowed to run in ConstrainedLanguage mode only.40        /// </summary>41        AllowConstrained = 3,42 43        /// <summary>44        /// Script file is allowed to run in FullLanguage mode but will emit ConstrainedLanguage restriction audit logs.45        /// </summary>46        AllowConstrainedAudit = 447    }48 49    /// <summary>50    /// How the policy is being enforced.51    /// </summary>52    // Internal Note: Current code that consumes this enum assumes that anything but 'Enforce' means53    // that the script is allowed, and that a system lockdown policy that is anything but 'None' means54    // that the API should be called again for individual files. If any elements are added to this enum,55    // callers of the GetLockdownPolicy() should be reviewed.56    public enum SystemEnforcementMode57    {58        /// Not enforced at all59        None = 0,60 61        /// Enabled - allow, but audit62        Audit = 1,63 64        /// Enabled, enforce restrictions65        Enforce = 266    }67 68    /// <summary>69    /// Support class for dealing with the Windows Lockdown Policy,70    /// Device Guard, and Constrained PowerShell.71    /// </summary>72    public sealed class SystemPolicy73    {74        private SystemPolicy()75        {76        }77 78        /// <summary>79        /// Writes to PowerShell WDAC Audit mode ETW log.80        /// </summary>81        /// <param name="context">Current execution context.</param>82        /// <param name="title">Audit message title.</param>83        /// <param name="message">Audit message message.</param>84        /// <param name="fqid">Fully Qualified ID.</param>85        /// <param name="dropIntoDebugger">Stops code execution and goes into debugger mode.</param>86        internal static void LogWDACAuditMessage(87            ExecutionContext context,88            string title,89            string message,90            string fqid,91            bool dropIntoDebugger = false)92        {93            string messageToWrite = message;94 95            // Augment the log message with current script information from the script debugger, if available.96            context ??= LocalPipeline.GetExecutionContextFromTLS();97            bool debuggerAvailable = context is not null &&98                                     context._debugger is ScriptDebugger;99 100            if (debuggerAvailable)101            {102                var scriptPosMessage = context._debugger.GetCurrentScriptPosition();103                if (!string.IsNullOrEmpty(scriptPosMessage))104                {105                    messageToWrite = message + scriptPosMessage;106                }107            }108 109            PSEtwLog.LogWDACAuditEvent(title, messageToWrite, fqid);110 111            // We drop into the debugger only if requested and we are running in the interactive host session runspace (Id == 1).112            if (debuggerAvailable && dropIntoDebugger &&113                context._debugger.DebugMode.HasFlag(DebugModes.LocalScript) &&114                Runspace.DefaultRunspace?.Id == 1 &&115                context.DebugPreferenceVariable.HasFlag(ActionPreference.Break) &&116                context.InternalHost?.UI is not null)117            {118                try119                {120                    context.InternalHost.UI.WriteLine();121                    context.InternalHost.UI.WriteLine("WDAC Audit Log:");122                    context.InternalHost.UI.WriteLine($"Title: {title}");123                    context.InternalHost.UI.WriteLine($"Message: {message}");124                    context.InternalHost.UI.WriteLine($"FullyQualifedId: {fqid}");125                    context.InternalHost.UI.WriteLine("Stopping script execution in debugger...");126                    context.InternalHost.UI.WriteLine();127 128                    context._debugger.Break();129                }130                catch131                { }132            }133        }134 135        /// <summary>136        /// Gets the system lockdown policy.137        /// </summary>138        /// <returns>An EnforcementMode that describes the system policy.</returns>139        public static SystemEnforcementMode GetSystemLockdownPolicy()140        {141            if (s_systemLockdownPolicy == null)142            {143                lock (s_systemLockdownPolicyLock)144                {145                    s_systemLockdownPolicy ??= GetLockdownPolicy(path: null, handle: null);146                }147            }148            else if (s_allowDebugOverridePolicy)149            {150                lock (s_systemLockdownPolicyLock)151                {152                    s_systemLockdownPolicy = GetDebugLockdownPolicy(path: null, out _);153                }154            }155 156            return s_systemLockdownPolicy.Value;157        }158 159        private static readonly object s_systemLockdownPolicyLock = new object();160        private static SystemEnforcementMode? s_systemLockdownPolicy = null;161        private static bool s_allowDebugOverridePolicy = false;162        private static bool s_wldpCanExecuteAvailable = true;163 164        /// <summary>165        /// Gets the system wide script file policy enforcement for an open file.166        /// Based on system WDAC (Windows Defender Application Control) or AppLocker policies.167        /// </summary>168        /// <param name="filePath">Script file path for policy check.</param>169        /// <param name="fileStream">FileStream object to script file path.</param>170        /// <returns>Policy check result for script file.</returns>171        public static SystemScriptFileEnforcement GetFilePolicyEnforcement(172            string filePath,173            System.IO.FileStream fileStream)174        {175            SafeHandle fileHandle = fileStream.SafeFileHandle;176            SystemEnforcementMode systemLockdownPolicy = GetSystemLockdownPolicy();177 178            // First check latest WDAC APIs if available.179            if (systemLockdownPolicy is SystemEnforcementMode.Enforce180                && s_wldpCanExecuteAvailable181                && TryGetWldpCanExecuteFileResult(filePath, fileHandle, out SystemScriptFileEnforcement wldpFilePolicy))182            {183                return GetLockdownPolicy(filePath, fileHandle, wldpFilePolicy);184            }185 186            // Failed to invoke WldpCanExecuteFile, revert to legacy APIs.187            if (systemLockdownPolicy is SystemEnforcementMode.None)188            {189                return SystemScriptFileEnforcement.None;190            }191 192            // WldpCanExecuteFile was invoked successfully so we can skip running193            // legacy WDAC APIs. AppLocker must still be checked in case it is more194            // strict than the current WDAC policy.195            return GetLockdownPolicy(filePath, fileHandle, canExecuteResult: null);196        }197 198        private static SystemScriptFileEnforcement ConvertToModernFileEnforcement(SystemEnforcementMode legacyMode)199        {200            return legacyMode switch201            {202                SystemEnforcementMode.None => SystemScriptFileEnforcement.Allow,203                SystemEnforcementMode.Audit => SystemScriptFileEnforcement.AllowConstrainedAudit,204                SystemEnforcementMode.Enforce => SystemScriptFileEnforcement.AllowConstrained,205                _ => SystemScriptFileEnforcement.Block,206            };207        }208 209        private static bool TryGetWldpCanExecuteFileResult(string filePath, SafeHandle fileHandle, out SystemScriptFileEnforcement result)210        {211            try212            {213                string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);214                string auditMsg = $"PowerShell ExternalScriptInfo reading file: {fileName}";215 216                int hr = WldpNativeMethods.WldpCanExecuteFile(217                    host: PowerShellHost,218                    options: WLDP_EXECUTION_EVALUATION_OPTIONS.WLDP_EXECUTION_EVALUATION_OPTION_NONE,219                    fileHandle: fileHandle.DangerousGetHandle(),220                    auditInfo: auditMsg,221                    result: out WLDP_EXECUTION_POLICY canExecuteResult);222 223                PSEtwLog.LogWDACQueryEvent("WldpCanExecuteFile", filePath, hr, (int)canExecuteResult);224 225                if (hr >= 0)226                {227                    switch (canExecuteResult)228                    {229                        case WLDP_EXECUTION_POLICY.WLDP_CAN_EXECUTE_ALLOWED:230                            result = SystemScriptFileEnforcement.Allow;231                            return true;232 233                        case WLDP_EXECUTION_POLICY.WLDP_CAN_EXECUTE_BLOCKED:234                            result = SystemScriptFileEnforcement.Block;235                            return true;236 237                        case WLDP_EXECUTION_POLICY.WLDP_CAN_EXECUTE_REQUIRE_SANDBOX:238                            result = SystemScriptFileEnforcement.AllowConstrained;239                            return true;240 241                        default:242                            // Fall through to legacy system policy checks.243                            Debug.Assert(false, $"Unknown policy result returned from WldCanExecute: {canExecuteResult}");244                            break;245                    }246                }247 248                // If HResult is unsuccessful (such as E_NOTIMPL (0x80004001)), fall through to legacy system checks.249            }250            catch (Exception ex) when (ex is DllNotFoundException or EntryPointNotFoundException)251            {252                // Fall back to legacy system policy checks.253                s_wldpCanExecuteAvailable = false;254                PSEtwLog.LogWDACQueryEvent("WldpCanExecuteFile_Failed", filePath, ex.HResult, 0);255            }256 257            result = default;258            return false;259        }260 261        /// <summary>262        /// Gets lockdown policy as applied to a file.263        /// </summary>264        /// <returns>An EnforcementMode that describes policy.</returns>265        public static SystemEnforcementMode GetLockdownPolicy(string path, SafeHandle handle)266        {267            SystemScriptFileEnforcement modernMode = GetLockdownPolicy(path, handle, canExecuteResult: null);268            Debug.Assert(269                modernMode is not SystemScriptFileEnforcement.Block,270                "Block should never be converted to legacy file enforcement.");271 272            return modernMode switch273            {274                SystemScriptFileEnforcement.Block => SystemEnforcementMode.Enforce,275                SystemScriptFileEnforcement.AllowConstrained => SystemEnforcementMode.Enforce,276                SystemScriptFileEnforcement.AllowConstrainedAudit => SystemEnforcementMode.Audit,277                SystemScriptFileEnforcement.Allow => SystemEnforcementMode.None,278                SystemScriptFileEnforcement.None => SystemEnforcementMode.None,279                _ => throw new ArgumentOutOfRangeException(nameof(modernMode)),280            };281        }282 283        private static SystemScriptFileEnforcement GetLockdownPolicy(284            string path,285            SafeHandle handle,286            SystemScriptFileEnforcement? canExecuteResult)287        {288            SystemScriptFileEnforcement wldpFilePolicy = canExecuteResult289                ?? ConvertToModernFileEnforcement(GetWldpPolicy(path, handle));290 291            // Check the WLDP File policy via API292            if (wldpFilePolicy is SystemScriptFileEnforcement.Block or SystemScriptFileEnforcement.AllowConstrained)293            {294                return wldpFilePolicy;295            }296 297            // Check the AppLocker File policy via API298            // This needs to be checked before WLDP audit policy299            // So, that we don't end up in Audit mode,300            // when we should be enforce mode.301            var appLockerFilePolicy = GetAppLockerPolicy(path, handle);302            if (appLockerFilePolicy == SystemEnforcementMode.Enforce)303            {304                return ConvertToModernFileEnforcement(appLockerFilePolicy);305            }306 307            // At this point, LockdownPolicy = Audit or Allowed.308            // If there was a WLDP policy, but WLDP didn't block it,309            // then it was explicitly allowed. Therefore, return the result for the file.310            if (s_cachedWldpSystemPolicy is SystemEnforcementMode.Audit or SystemEnforcementMode.Enforce311                || wldpFilePolicy is SystemScriptFileEnforcement.AllowConstrainedAudit)312            {313                return wldpFilePolicy;314            }315 316            // If there was a system-wide AppLocker policy, but AppLocker didn't block it,317            // then return AppLocker's status.318            if (s_cachedSaferSystemPolicy is SaferPolicy.Disallowed)319            {320                return ConvertToModernFileEnforcement(appLockerFilePolicy);321            }322 323            // If it's not set to 'Enforce' by the platform, allow debug overrides324            GetDebugLockdownPolicy(path, out SystemScriptFileEnforcement debugPolicy);325            return debugPolicy;326        }327 328        [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods",329            MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]330        private static SystemEnforcementMode GetWldpPolicy(string path, SafeHandle handle)331        {332            // If the WLDP assembly is missing (such as windows 7 or down OS), return default/None to skip WLDP validation333            if (s_hadMissingWldpAssembly)334            {335                return s_cachedWldpSystemPolicy.GetValueOrDefault(SystemEnforcementMode.None);336            }337 338            // If path is NULL, see if we have the cached system-wide lockdown policy.339            if (string.IsNullOrEmpty(path))340            {341                if ((s_cachedWldpSystemPolicy != null) && (!InternalTestHooks.BypassAppLockerPolicyCaching))342                {343                    return s_cachedWldpSystemPolicy.Value;344                }345            }346 347            try348            {349                WLDP_HOST_INFORMATION hostInformation = new WLDP_HOST_INFORMATION();350                hostInformation.dwRevision = WldpNativeConstants.WLDP_HOST_INFORMATION_REVISION;351                hostInformation.dwHostId = WLDP_HOST_ID.WLDP_HOST_ID_POWERSHELL;352 353                if (!string.IsNullOrEmpty(path))354                {355                    hostInformation.szSource = path;356 357                    if (handle != null)358                    {359                        IntPtr fileHandle = IntPtr.Zero;360                        fileHandle = handle.DangerousGetHandle();361                        hostInformation.hSource = fileHandle;362                    }363                }364 365                uint pdwLockdownState = 0;366                int result = WldpNativeMethods.WldpGetLockdownPolicy(ref hostInformation, ref pdwLockdownState, 0);367                PSEtwLog.LogWDACQueryEvent("WldpGetLockdownPolicy", path, result, (int)pdwLockdownState);368                if (result >= 0)369                {370                    SystemEnforcementMode resultingLockdownPolicy = GetLockdownPolicyForResult(pdwLockdownState);371 372                    // If this is a query for the system-wide lockdown policy, cache it.373                    if (string.IsNullOrEmpty(path))374                    {375                        s_cachedWldpSystemPolicy = resultingLockdownPolicy;376                    }377 378                    return resultingLockdownPolicy;379                }380                else381                {382                    // API failure?383                    return SystemEnforcementMode.Enforce;384                }385            }386            catch (DllNotFoundException ex)387            {388                s_hadMissingWldpAssembly = true;389                PSEtwLog.LogWDACQueryEvent("WldpGetLockdownPolicy_Failed", path, ex.HResult, 0);390                return s_cachedWldpSystemPolicy.GetValueOrDefault(SystemEnforcementMode.None);391            }392        }393 394        private static SystemEnforcementMode? s_cachedWldpSystemPolicy = null;395 396        private const string AppLockerTestFileName = "__PSScriptPolicyTest_";397        private const string AppLockerTestFileContents = "# PowerShell test file to determine AppLocker lockdown mode ";398 399        private static SystemEnforcementMode GetAppLockerPolicy(string path, SafeHandle handle)400        {401            SaferPolicy result = SaferPolicy.Disallowed;402 403            // If path is NULL, we're looking for the system-wide lockdown policy.404            // Since there is no way to get that from AppLocker, we will test the policy405            // against a random non-existent script and module. If that is allowed, then there is406            // no AppLocker script policy.407            if (string.IsNullOrEmpty(path))408            {409                if ((s_cachedSaferSystemPolicy != null) && (!InternalTestHooks.BypassAppLockerPolicyCaching))410                {411                    result = s_cachedSaferSystemPolicy.Value;412                }413                else414                {415                    //416                    // Temp path can sometimes be deleted. While many places in PowerShell depend on its existence,417                    // this one can crash PowerShell.418                    // A less sensitive implementation will be possible once AppLocker allows validation of files that419                    // don't exist.420                    //421 422                    string testPathScript = null;423                    string testPathModule = null;424                    try425                    {426                        // Start with the current profile temp path.427                        string tempPath = IO.Path.GetTempPath();428 429                        int iteration = 0;430                        while (iteration++ < 2)431                        {432                            bool error = false;433 434                            try435                            {436                                if (!IO.Directory.Exists(tempPath))437                                {438                                    IO.Directory.CreateDirectory(tempPath);439                                }440 441                                testPathScript = IO.Path.Combine(tempPath, AppLockerTestFileName + IO.Path.GetRandomFileName() + ".ps1");442                                testPathModule = IO.Path.Combine(tempPath, AppLockerTestFileName + IO.Path.GetRandomFileName() + ".psm1");443 444                                // AppLocker fails when you try to check a policy on a file445                                // with no content. So create a scratch file and test on that.446                                string dtAppLockerTestFileContents = AppLockerTestFileContents + Environment.TickCount64;447                                IO.File.WriteAllText(testPathScript, dtAppLockerTestFileContents);448                                IO.File.WriteAllText(testPathModule, dtAppLockerTestFileContents);449                            }450                            catch (IO.IOException)451                            {452                                if (iteration == 2)453                                {454                                    throw;455                                }456 457                                error = true;458                            }459                            catch (UnauthorizedAccessException)460                            {461                                if (iteration == 2)462                                {463                                    throw;464                                }465 466                                error = true;467                            }468                            catch (System.Security.SecurityException)469                            {470                                if (iteration == 2)471                                {472                                    throw;473                                }474 475                                error = true;476                            }477 478                            if (!error)479                            {480                                break;481                            }482 483                            // Try again with the AppData\LocalLow\Temp path using known folder id:484                            // https://msdn.microsoft.com/library/dd378457.aspx485                            Guid AppDatalocalLowFolderId = new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16");486                            tempPath = GetKnownFolderPath(AppDatalocalLowFolderId) + @"\Temp";487                        }488 489                        // Test policy.490                        result = TestSaferPolicy(testPathScript, testPathModule);491                    }492                    catch (System.IO.IOException)493                    {494                        // If we fail to test the policy, assume the default.495                        result = SaferPolicy.Disallowed;496                    }497                    catch (System.UnauthorizedAccessException)498                    {499                        // This can happen during thread impersonation if the profile temp paths are not accessible.500                        // Allow policy if impersonated, otherwise disallow.501                        result =502                            (System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel == System.Security.Principal.TokenImpersonationLevel.Impersonation) ?503                            SaferPolicy.Allowed : SaferPolicy.Disallowed;504                    }505                    catch (ArgumentException)506                    {507                        // This is for IO.Path.GetTempPath() call when temp paths are not accessible.508                        result =509                           (System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel == System.Security.Principal.TokenImpersonationLevel.Impersonation) ?510                           SaferPolicy.Allowed : SaferPolicy.Disallowed;511                    }512                    finally513                    {514                        // Ok to leave the test scripts in the temp folder if they happen to be in use515                        // so that PowerShell will still startup.516                        PathUtils.TryDeleteFile(testPathScript);517                        PathUtils.TryDeleteFile(testPathModule);518                    }519 520                    s_cachedSaferSystemPolicy = result;521                }522 523                if (result == SaferPolicy.Disallowed)524                {525                    return SystemEnforcementMode.Enforce;526                }527                else528                {529                    return SystemEnforcementMode.None;530                }531            }532            else533            {534                // We got a path. Return the result for that path.535                result = SecuritySupport.GetSaferPolicy(path, handle);536                if (result == SaferPolicy.Disallowed)537                {538                    return SystemEnforcementMode.Enforce;539                }540 541                return SystemEnforcementMode.None;542            }543        }544 545        private static SaferPolicy? s_cachedSaferSystemPolicy = null;546 547        private static string GetKnownFolderPath(Guid knownFolderId)548        {549            IntPtr pszPath = IntPtr.Zero;550            try551            {552                int hr = WldpNativeMethods.SHGetKnownFolderPath(knownFolderId, 0, IntPtr.Zero, out pszPath);553                if (hr >= 0)554                {555                    return Marshal.PtrToStringAuto(pszPath);556                }557 558                throw new System.IO.IOException();559            }560            finally561            {562                if (pszPath != IntPtr.Zero)563                {564                    Marshal.FreeCoTaskMem(pszPath);565                }566            }567        }568 569        private static SaferPolicy TestSaferPolicy(string testPathScript, string testPathModule)570        {571            SaferPolicy result = SecuritySupport.GetSaferPolicy(testPathScript, null);572            if (result == SaferPolicy.Disallowed)573            {574                result = SecuritySupport.GetSaferPolicy(testPathModule, null);575            }576 577            return result;578        }579 580        private static SystemEnforcementMode GetDebugLockdownPolicy(string path, out SystemScriptFileEnforcement modernEnforcement)581        {582            s_allowDebugOverridePolicy = true;583 584            // Support fall-back debug hook for path exclusions on non-WOA platforms585            if (path != null)586            {587                // Assume everything under SYSTEM32 is trusted, with a purposefully sloppy588                // check so that we can actually put it in the filename during testing.589                if (path.Contains("System32", StringComparison.OrdinalIgnoreCase))590                {591                    modernEnforcement = SystemScriptFileEnforcement.Allow;592                    return SystemEnforcementMode.None;593                }594 595                // No explicit debug allowance for the file, so return the system policy if there is one.596                modernEnforcement = s_systemLockdownPolicy switch597                {598                    SystemEnforcementMode.Enforce => SystemScriptFileEnforcement.AllowConstrained,599                    SystemEnforcementMode.Audit => SystemScriptFileEnforcement.AllowConstrainedAudit,600                    SystemEnforcementMode.None => SystemScriptFileEnforcement.None,601                    _ => SystemScriptFileEnforcement.None,602                };603 604                return s_systemLockdownPolicy.GetValueOrDefault(SystemEnforcementMode.None);605            }606 607            // Support fall-back debug hook for system-wide policy on non-WOA platforms608            uint pdwLockdownState = 0;609            object result = Environment.GetEnvironmentVariable("__PSLockdownPolicy", EnvironmentVariableTarget.Machine);610            if (result != null)611            {612                pdwLockdownState = LanguagePrimitives.ConvertTo<uint>(result);613                SystemEnforcementMode policy = GetLockdownPolicyForResult(pdwLockdownState);614                modernEnforcement = ConvertToModernFileEnforcement(policy);615                return policy;616            }617 618            // If the system-wide debug policy had no preference, then there is no enforcement.619            modernEnforcement = SystemScriptFileEnforcement.None;620            return SystemEnforcementMode.None;621        }622 623        private static bool s_hadMissingWldpAssembly = false;624 625        /// <summary>626        /// Gets lockdown policy as applied to a COM object.627        /// </summary>628        /// <returns>True if the COM object is allowed, False otherwise.</returns>629        internal static bool IsClassInApprovedList(Guid clsid)630        {631            // This method is called only if there is an AppLocker and/or WLDP system wide lock down enforcement policy.632            if (s_cachedWldpSystemPolicy.GetValueOrDefault(SystemEnforcementMode.None) != SystemEnforcementMode.Enforce)633            {634                // No WLDP policy implies only AppLocker policy enforcement. Disallow all COM object instantiation.635                return false;636            }637 638            // WLDP policy must be in system wide enforcement, look up COM Id in WLDP approval list.639            try640            {641                WLDP_HOST_INFORMATION hostInformation = new WLDP_HOST_INFORMATION();642                hostInformation.dwRevision = WldpNativeConstants.WLDP_HOST_INFORMATION_REVISION;643                hostInformation.dwHostId = WLDP_HOST_ID.WLDP_HOST_ID_POWERSHELL;644 645                int pIsApproved = 0;646                int result = WldpNativeMethods.WldpIsClassInApprovedList(ref clsid, ref hostInformation, ref pIsApproved, 0);647 648                if (result >= 0)649                {650                    if (pIsApproved == 1)651                    {652                        // Hook for testability. If we've got an environmental override, say that ADODB.Parameter653                        // is not allowed.654                        // 0000050b-0000-0010-8000-00aa006d2ea4 = ADODB.Parameter655                        if (s_allowDebugOverridePolicy)656                        {657                            if (string.Equals(clsid.ToString(), "0000050b-0000-0010-8000-00aa006d2ea4", StringComparison.OrdinalIgnoreCase))658                            {659                                return false;660                            }661                        }662 663                        return true;664                    }665                }666 667                return false;668            }669            catch (DllNotFoundException)670            {671                // Hook for testability. IsClassInApprovedList is only called when the system is in global lockdown mode,672                // so this wouldn't be allowed in regular ConstrainedLanguage mode.673                // f6d90f11-9c73-11d3-b32e-00c04f990bb4 = MSXML2.DOMDocument674                if (string.Equals(clsid.ToString(), "f6d90f11-9c73-11d3-b32e-00c04f990bb4", StringComparison.OrdinalIgnoreCase))675                {676                    return true;677                }678 679                return false;680            }681        }682 683        private static SystemEnforcementMode GetLockdownPolicyForResult(uint pdwLockdownState)684        {685            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_UMCIAUDIT_FLAG) ==686                SystemPolicy.WldpNativeConstants.WLDP_LOCKDOWN_UMCIAUDIT_FLAG)687            {688                return SystemEnforcementMode.Audit;689            }690            else if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_UMCIENFORCE_FLAG) ==691                WldpNativeConstants.WLDP_LOCKDOWN_UMCIENFORCE_FLAG)692            {693                return SystemEnforcementMode.Enforce;694            }695            else696            {697                return SystemEnforcementMode.None;698            }699        }700 701        internal static string DumpLockdownState(uint pdwLockdownState)702        {703            string returnValue = string.Empty;704 705            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_DEFINED_FLAG) == WldpNativeConstants.WLDP_LOCKDOWN_DEFINED_FLAG)706            {707                returnValue += "WLDP_LOCKDOWN_DEFINED_FLAG\r\n";708            }709 710            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_SECUREBOOT_FLAG) == WldpNativeConstants.WLDP_LOCKDOWN_SECUREBOOT_FLAG)711            {712                returnValue += "WLDP_LOCKDOWN_SECUREBOOT_FLAG\r\n";713            }714 715            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_DEBUGPOLICY_FLAG) == WldpNativeConstants.WLDP_LOCKDOWN_DEBUGPOLICY_FLAG)716            {717                returnValue += "WLDP_LOCKDOWN_DEBUGPOLICY_FLAG\r\n";718            }719 720            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_UMCIENFORCE_FLAG) == WldpNativeConstants.WLDP_LOCKDOWN_UMCIENFORCE_FLAG)721            {722                returnValue += "WLDP_LOCKDOWN_UMCIENFORCE_FLAG\r\n";723            }724 725            if ((pdwLockdownState & WldpNativeConstants.WLDP_LOCKDOWN_UMCIAUDIT_FLAG) == WldpNativeConstants.WLDP_LOCKDOWN_UMCIAUDIT_FLAG)726            {727                returnValue += "WLDP_LOCKDOWN_UMCIAUDIT_FLAG\r\n";728            }729 730            return returnValue;731        }732 733        // Overrides for features that should only be enabled in debug mode734        internal static bool XamlWorkflowSupported { get; set; }735 736        /// <summary>737        /// Native constants for dealing with the lockdown policy.738        /// </summary>739        internal static class WldpNativeConstants740        {741            internal const uint WLDP_HOST_INFORMATION_REVISION = 0x00000001;742 743            internal const uint WLDP_LOCKDOWN_UNDEFINED = 0;744            internal const uint WLDP_LOCKDOWN_DEFINED_FLAG = 0x80000000;745            internal const uint WLDP_LOCKDOWN_SECUREBOOT_FLAG = 1;746            internal const uint WLDP_LOCKDOWN_DEBUGPOLICY_FLAG = 2;747            internal const uint WLDP_LOCKDOWN_UMCIENFORCE_FLAG = 4;748            internal const uint WLDP_LOCKDOWN_UMCIAUDIT_FLAG = 8;749        }750 751        /// <summary>752        /// The different host IDs understood by the lockdown policy.753        /// </summary>754        internal enum WLDP_HOST_ID755        {756            WLDP_HOST_ID_UNKNOWN = 0,757            WLDP_HOST_ID_GLOBAL = 1,758            WLDP_HOST_ID_VBA = 2,759            WLDP_HOST_ID_WSH = 3,760            WLDP_HOST_ID_POWERSHELL = 4,761            WLDP_HOST_ID_IE = 5,762            WLDP_HOST_ID_MSI = 6,763            WLDP_HOST_ID_MAX = 7,764        }765 766        /// <summary>767        /// Host information structure to contain the lockdown policy request.768        /// </summary>769        [StructLayoutAttribute(LayoutKind.Sequential)]770        internal struct WLDP_HOST_INFORMATION771        {772            /// DWORD->unsigned int773            internal uint dwRevision;774 775            /// WLDP_HOST_ID->_WLDP_HOST_ID776            internal WLDP_HOST_ID dwHostId;777 778            /// PCWSTR->WCHAR*779            [MarshalAsAttribute(UnmanagedType.LPWStr)]780            internal string szSource;781 782            // HANDLE->IntPtr783            internal IntPtr hSource;784        }785 786        /// <summary>787        /// Options for WldpCanExecuteFile method.788        /// </summary>789        [Flags]790        internal enum WLDP_EXECUTION_EVALUATION_OPTIONS791        {792            WLDP_EXECUTION_EVALUATION_OPTION_NONE = 0x0,793            WLDP_EXECUTION_EVALUATION_OPTION_EXECUTE_IN_INTERACTIVE_SESSION = 0x1794        }795 796        /// <summary>797        /// Results from WldpCanExecuteFile method.798        /// </summary>799        internal enum WLDP_EXECUTION_POLICY800        {801            WLDP_CAN_EXECUTE_BLOCKED = 0,802            WLDP_CAN_EXECUTE_ALLOWED = 1,803            WLDP_CAN_EXECUTE_REQUIRE_SANDBOX = 2804        }805 806        /// <summary>807        /// Powershell Script Host.808        /// </summary>809        internal static readonly Guid PowerShellHost = new Guid("8E9AAA7C-198B-4879-AE41-A50D47AD6458");810 811        /// <summary>812        /// Native methods for dealing with the lockdown policy.813        /// </summary>814        internal static class WldpNativeMethods815        {816            /// <summary>817            /// Returns a WLDP_EXECUTION_POLICY enum value indicating if and how a script file818            /// should be executed.819            /// </summary>820            /// <param name="host">Host guid.</param>821            /// <param name="options">Evaluation options.</param>822            /// <param name="fileHandle">Evaluated file handle.</param>823            /// <param name="auditInfo">Auditing information string.</param>824            /// <param name="result">Evaluation result.</param>825            /// <returns>HResult value.</returns>826            [DefaultDllImportSearchPathsAttribute(DllImportSearchPath.System32)]827            [DllImportAttribute("wldp.dll", EntryPoint = "WldpCanExecuteFile")]828            internal static extern int WldpCanExecuteFile(829                [MarshalAs(UnmanagedType.LPStruct)]830                Guid host,831                WLDP_EXECUTION_EVALUATION_OPTIONS options,832                IntPtr fileHandle,833                [MarshalAs(UnmanagedType.LPWStr)]834                string auditInfo,835                out WLDP_EXECUTION_POLICY result);836 837            /// Return Type: HRESULT->LONG->int838            /// pHostInformation: PWLDP_HOST_INFORMATION->_WLDP_HOST_INFORMATION*839            /// pdwLockdownState: PDWORD->DWORD*840            /// dwFlags: DWORD->unsigned int841            [DefaultDllImportSearchPathsAttribute(DllImportSearchPath.System32)]842            [DllImportAttribute("wldp.dll", EntryPoint = "WldpGetLockdownPolicy")]843            internal static extern int WldpGetLockdownPolicy(844                ref WLDP_HOST_INFORMATION pHostInformation,845                ref uint pdwLockdownState,846                uint dwFlags);847 848            /// Return Type: HRESULT->LONG->int849            /// rclsid: IID*850            /// pHostInformation: PWLDP_HOST_INFORMATION->_WLDP_HOST_INFORMATION*851            /// ptIsApproved: PBOOL->BOOL*852            /// dwFlags: DWORD->unsigned int853            [DefaultDllImportSearchPathsAttribute(DllImportSearchPath.System32)]854            [DllImportAttribute("wldp.dll", EntryPoint = "WldpIsClassInApprovedList")]855            internal static extern int WldpIsClassInApprovedList(856                ref Guid rclsid,857                ref WLDP_HOST_INFORMATION pHostInformation,858                ref int ptIsApproved,859                uint dwFlags);860 861            [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]862            internal static extern int SHGetKnownFolderPath(863                [MarshalAs(UnmanagedType.LPStruct)]864                Guid rfid,865                int dwFlags,866                IntPtr hToken,867                out IntPtr pszPath);868        }869    }870}871 872#endif873