/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using Dbg=System.Management.Automation; using System.Reflection; using System.Collections; using System.Security; using System.Management.Automation.Host; namespace System.Management.Automation { /// /// This enum defines the dispatch origin of a command. /// public enum CommandOrigin { /// /// The command was submitted via a runspace. /// Runspace, /// /// The command was dispatched by the msh engine as a result of /// a dispatch request from an already running command. /// Internal } /// /// Defines the base class for an authorization manager of a Runspace. /// /// An authorization manager helps a host control and restrict the /// execution of commands. For each of the command types listed in /// the /// enumeration, the engine requests permission from the AuthorizationManager /// to run the command. /// /// Extending this class requires that you override the ShouldRun method with /// the logic specific to your needs. The base class gives permission to run /// every command. The default /// Microsoft.PowerShell.PSAuthorizationManager /// provides a customized and much more complete authorization policy. /// public class AuthorizationManager { #region constructor private string shellId; /// /// Creates an instance of authorization manager using specified shellID /// /// /// public AuthorizationManager(string shellId) { this.shellId = shellId; } #endregion constructor private object policyCheckLock = new object(); #region methods to use internally /// /// determine if we should run the specified file /// /// /// info on entity to be run /// /// the dispatch origin of a command /// /// allows access to the host. /// /// /// This method throws SecurityException in case running is not allowed. /// /// /// /// If the derived security manager threw an exception or returned /// false with a reason. /// /// internal void ShouldRunInternal(CommandInfo commandInfo, CommandOrigin origin, PSHost host) { // TODO:PSL this is a workaround since the exception below // hides the internal issue of what's going on in terms of // execution policy. if (Platform.IsCore) { return; } #if DEBUG // If we are debugging, let the unit tests swap the file from beneath us if(commandInfo.CommandType == CommandTypes.ExternalScript) { while(Environment.GetEnvironmentVariable("PSCommandDiscoveryPreDelay") != null) { System.Threading.Thread.Sleep(100); } } #endif bool result = false; bool defaultCatch = false; Exception authorizationManagerException = null; try { lock (policyCheckLock) { result = this.ShouldRun(commandInfo, origin, host, out authorizationManagerException); } #if DEBUG // If we are debugging, let the unit tests swap the file from beneath us if(commandInfo.CommandType == CommandTypes.ExternalScript) { while(Environment.GetEnvironmentVariable("PSCommandDiscoveryPostDelay") != null) { System.Threading.Thread.Sleep(100); } } #endif } catch (Exception e) // Catch-all OK. 3rd party callout { CommandProcessorBase.CheckForSevereException(e); authorizationManagerException = e; defaultCatch = true; result = false; } if (!result) { if (authorizationManagerException != null) { if (authorizationManagerException is PSSecurityException) { throw authorizationManagerException; } else { string message = authorizationManagerException.Message; if (defaultCatch) { message = AuthorizationManagerBase.AuthorizationManagerDefaultFailureReason; } PSSecurityException securityException = new PSSecurityException(message, authorizationManagerException); throw securityException; } } else { throw new PSSecurityException(AuthorizationManagerBase.AuthorizationManagerDefaultFailureReason); } } } /// /// Get the shell ID from the authorization manager... /// internal string ShellId { get { return shellId; } } #endregion methods to use internally #region methods for derived class to override /// /// Determines if the host should run the command a specified by the CommandInfo parameter. /// The default implementation gives permission to run every command. /// /// /// Information about the command to be run /// /// The origin of the command /// /// The host running the command /// /// The reason for preventing execution, if applicable /// /// True if the host should run the command. False otherwise /// protected internal virtual bool ShouldRun(CommandInfo commandInfo, CommandOrigin origin, PSHost host, out Exception reason) { Dbg.Diagnostics.Assert(commandInfo != null, "caller should validate the parameter"); reason = null; return true; } #endregion methods for derived class to override } }