2 // System.Security.SecurityManager.cs
5 // Nick Drochak(ndrochak@gol.com)
6 // Sebastien Pouliot <sebastien@ximian.com>
9 // Portions (C) 2004 Motus Technologies Inc. (http://www.motus.com)
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Globalization;
35 using System.Reflection;
36 using System.Security.Permissions;
37 using System.Security.Policy;
41 namespace System.Security {
43 // Note: Using [SecurityPermissionAttribute] would be cool but triggers an error
44 // as you can't reference a custom security attribute from it's own assembly (CS0647)
46 public sealed class SecurityManager {
48 private static bool checkExecutionRights;
49 private static bool securityEnabled;
50 private static object _lockObject;
51 private static ArrayList _hierarchy;
53 static SecurityManager ()
56 // http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp?frame=true
57 _lockObject = new object ();
58 securityEnabled = true;
59 // checkExecutionRights = true;
62 private SecurityManager ()
68 public static bool CheckExecutionRights {
69 get { return checkExecutionRights; }
71 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
73 // throw a SecurityException if we don't have ControlPolicy permission
74 checkExecutionRights = value;
78 public static bool SecurityEnabled {
79 get { return securityEnabled; }
81 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
83 // throw a SecurityException if we don't have ControlPolicy permission
84 securityEnabled = value;
92 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey = "0x00000000000000000400000000000000")]
93 public static void GetZoneAndOrigin (out ArrayList zone, out ArrayList origin)
100 public static bool IsGranted (IPermission perm)
104 if (!securityEnabled)
108 // - Only check the caller (no stack walk required)
109 // - Not affected by overrides (like Assert, Deny and PermitOnly)
110 return Assembly.GetCallingAssembly ().Demand (perm);
113 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
114 public static PolicyLevel LoadPolicyLevelFromFile (string path, PolicyLevelType type)
116 // throw a SecurityException if we don't have ControlPolicy permission
118 throw new ArgumentNullException ("path");
120 PolicyLevel pl = null;
122 pl = new PolicyLevel (type.ToString (), PolicyLevelType.AppDomain);
123 pl.LoadFromFile (path);
125 catch (Exception e) {
126 throw new ArgumentException (Locale.GetText ("Invalid policy XML"), e);
131 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
132 public static PolicyLevel LoadPolicyLevelFromString (string str, PolicyLevelType type)
134 // throw a SecurityException if we don't have ControlPolicy permission
136 throw new ArgumentNullException ("str");
138 PolicyLevel pl = null;
140 pl = new PolicyLevel (type.ToString (), PolicyLevelType.AppDomain);
141 pl.LoadFromString (str);
143 catch (Exception e) {
144 throw new ArgumentException (Locale.GetText ("Invalid policy XML"), e);
149 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
150 public static IEnumerator PolicyHierarchy ()
152 // throw a SecurityException if we don't have ControlPolicy permission
156 public static PermissionSet ResolvePolicy (Evidence evidence)
158 // no evidence, no permission
159 if (evidence == null)
160 return new PermissionSet (PermissionState.None);
162 PermissionSet ps = null;
163 // Note: can't call PolicyHierarchy since ControlPolicy isn't required to resolve policies
164 IEnumerator ple = Hierarchy;
165 while (ple.MoveNext ()) {
166 PolicyLevel pl = (PolicyLevel) ple.Current;
167 PolicyStatement pst = pl.Resolve (evidence);
170 ps = pst.PermissionSet;
172 ps = ps.Intersect (pst.PermissionSet);
174 if ((pst.Attributes & PolicyStatementAttribute.LevelFinal) == PolicyStatementAttribute.LevelFinal)
179 // Only host evidence are used for policy resolution
180 IEnumerator ee = evidence.GetHostEnumerator ();
181 while (ee.MoveNext ()) {
182 IIdentityPermissionFactory ipf = (ee.Current as IIdentityPermissionFactory);
184 IPermission p = ipf.CreateIdentityPermission (evidence);
185 ps.AddPermission (p);
193 public static PermissionSet ResolvePolicy (Evidence[] evidences)
195 // probably not optimal
196 PermissionSet ps = null;
197 foreach (Evidence evidence in evidences) {
199 ps = ResolvePolicy (evidence);
201 ps = ps.Intersect (ResolvePolicy (evidence));
207 static private SecurityPermission _execution = new SecurityPermission (SecurityPermissionFlag.Execution);
210 public static PermissionSet ResolvePolicy (Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, out PermissionSet denied)
212 PermissionSet resolved = ResolvePolicy (evidence);
213 // do we have the minimal permission requested by the assembly ?
214 if ((reqdPset != null) && !reqdPset.IsSubsetOf (resolved)) {
215 throw new PolicyException (Locale.GetText (
216 "Policy doesn't grant the minimal permissions required to execute the assembly."));
218 // do we have the right to execute ?
219 if (checkExecutionRights) {
220 // unless we have "Full Trust"...
221 if (!resolved.IsUnrestricted ()) {
222 // ... we need to find a SecurityPermission
223 IPermission security = resolved.GetPermission (typeof (SecurityPermission));
224 if (!_execution.IsSubsetOf (security)) {
225 throw new PolicyException (Locale.GetText (
226 "Policy doesn't grant the right to execute to the assembly."));
235 public static IEnumerator ResolvePolicyGroups (Evidence evidence)
237 if (evidence == null)
238 throw new ArgumentNullException ("evidence");
240 ArrayList al = new ArrayList ();
241 // Note: can't call PolicyHierarchy since ControlPolicy isn't required to resolve policies
242 IEnumerator ple = Hierarchy;
243 while (ple.MoveNext ()) {
244 PolicyLevel pl = (PolicyLevel) ple.Current;
245 CodeGroup cg = pl.ResolveMatchingCodeGroups (evidence);
248 return al.GetEnumerator ();
251 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
252 public static void SavePolicy ()
254 // throw a SecurityException if we don't have ControlPolicy permission
255 IEnumerator e = Hierarchy;
256 while (e.MoveNext ()) {
257 PolicyLevel level = (e.Current as PolicyLevel);
262 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
263 public static void SavePolicyLevel (PolicyLevel level)
265 // Yes this will throw a NullReferenceException, just like MS (see FDBK13121)
269 // private/internal stuff
271 private static IEnumerator Hierarchy {
273 if (_hierarchy == null) {
275 InitializePolicyHierarchy ();
278 return _hierarchy.GetEnumerator ();
282 private static void InitializePolicyHierarchy ()
284 string machinePolicyPath = Path.GetDirectoryName (Environment.GetMachineConfigPath ());
285 string userPolicyPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), "mono");
287 ArrayList al = new ArrayList ();
288 al.Add (new PolicyLevel ("Enterprise", PolicyLevelType.Enterprise,
289 Path.Combine (machinePolicyPath, "enterprisesec.config")));
291 al.Add (new PolicyLevel ("Machine", PolicyLevelType.Machine,
292 Path.Combine (machinePolicyPath, "security.config")));
294 al.Add (new PolicyLevel ("User", PolicyLevelType.User,
295 Path.Combine (userPolicyPath, "security.config")));
297 _hierarchy = ArrayList.Synchronized (al);