-
Notifications
You must be signed in to change notification settings - Fork 8.4k
Expand file tree
/
Copy pathSecurityManagerBase.cs
More file actions
183 lines (159 loc) · 6.67 KB
/
Copy pathSecurityManagerBase.cs
File metadata and controls
183 lines (159 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Management.Automation.Host;
using Dbg = System.Management.Automation;
namespace System.Management.Automation
{
/// <summary>
/// This enum defines the dispatch origin of a command.
/// </summary>
public enum CommandOrigin
{
/// <summary>
/// The command was submitted via a runspace.
/// </summary>
Runspace,
/// <summary>
/// The command was dispatched by the engine as a result of
/// a dispatch request from an already running command.
/// </summary>
Internal
}
/// <summary>
/// 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 <see cref="System.Management.Automation.CommandTypes"/>
/// 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.
/// </summary>
public class AuthorizationManager
{
#region constructor
/// <summary>
/// Creates an instance of authorization manager using specified shellID.
/// </summary>
/// <param name="shellId">
/// </param>
public AuthorizationManager(string shellId)
{
ShellId = shellId;
}
#endregion constructor
private readonly object _policyCheckLock = new object();
#region methods to use internally
/// <summary>
/// Determine if we should run the specified file.
/// </summary>
/// <param name="commandInfo">Info on entity to be run.</param>
/// <param name="origin">The dispatch origin of a command.</param>
/// <param name="host">Allows access to the host.</param>
/// <remarks>
/// This method throws SecurityException in case running is not allowed.
/// </remarks>
/// <exception cref="System.Management.Automation.PSSecurityException">
/// If the derived security manager threw an exception or returned
/// false with a reason.
/// </exception>
internal void ShouldRunInternal(CommandInfo commandInfo,
CommandOrigin origin,
PSHost host)
{
#if UNIX
// TODO:PSL this is a workaround since the exception below
// hides the internal issue of what's going on in terms of
// execution policy.
// On non-Windows platform Set/Get-ExecutionPolicy throw
// PlatformNotSupportedException
return;
#else
#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
{
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);
}
}
#endif
}
/// <summary>
/// Get the shell ID from the authorization manager...
/// </summary>
internal string ShellId { get; }
#endregion methods to use internally
#region methods for derived class to override
/// <summary>
/// Determines if the host should run the command a specified by the CommandInfo parameter.
/// The default implementation gives permission to run every command.
/// </summary>
/// <param name="commandInfo">Information about the command to be run.</param>
/// <param name="origin">The origin of the command.</param>
/// <param name="host">The host running the command.</param>
/// <param name="reason">The reason for preventing execution, if applicable.</param>
/// <returns>True if the host should run the command. False otherwise.</returns>
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
}
}