2 // System.Security.Policy.PolicyLevel.cs
5 // Nick Drochak (ndrochak@gol.com)
6 // Duncan Mak (duncan@ximian.com)
7 // Sebastien Pouliot <sebastien@ximian.com>
9 // (C) 2001 Nick Drochak
10 // (C) 2003 Duncan Mak, Ximian Inc.
11 // Portions (C) 2004 Motus Technologies Inc. (http://www.motus.com)
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections; // for IList
35 using System.Globalization;
37 using System.Reflection;
38 using System.Security;
39 using System.Security.Permissions;
43 namespace System.Security.Policy {
46 public sealed class PolicyLevel {
49 CodeGroup root_code_group;
50 private ArrayList full_trust_assemblies;
51 private ArrayList named_permission_sets;
52 private string _location;
53 private PolicyLevelType _type;
54 private Hashtable fullNames;
56 internal PolicyLevel (string label, PolicyLevelType type)
60 full_trust_assemblies = new ArrayList ();
61 named_permission_sets = new ArrayList ();
64 internal PolicyLevel (string label, PolicyLevelType type, string filename)
67 LoadFromFile (filename);
70 internal void LoadFromFile (string filename)
74 // check for policy file
75 if (!File.Exists (filename)) {
76 // if it doesn't exist use the default configuration (like Fx 2.0)
77 // ref: http://blogs.msdn.com/shawnfa/archive/2004/04/21/117833.aspx
78 string defcfg = filename + ".default";
79 if (File.Exists (defcfg)) {
80 // create policy from default file
81 File.Copy (defcfg, filename);
84 // load security policy configuration
85 if (File.Exists (filename)) {
86 using (StreamReader sr = File.OpenText (filename)) {
87 LoadFromString (sr.ReadToEnd ());
92 CreateFromHardcodedDefault (_type);
97 /* catch (Exception) {
98 // this can fail in many ways include
99 // * can't lookup policy (path discovery);
100 // * can't copy default file to policy
101 // * can't read policy file;
102 // * can't save hardcoded policy to filename
103 // * can't decode policy file
105 CreateFromHardcodedDefault (_type);
108 _location = filename;
112 internal void LoadFromString (string xml)
114 SecurityParser parser = new SecurityParser ();
115 parser.LoadXml (xml);
116 // configuration / mscorlib / security / policy / PolicyLevel
117 SecurityElement configuration = parser.ToXml ();
118 if (configuration.Tag != "configuration")
119 throw new ArgumentException (Locale.GetText ("missing <configuration> root element"));
120 SecurityElement mscorlib = (SecurityElement) configuration.Children [0];
121 if (mscorlib.Tag != "mscorlib")
122 throw new ArgumentException (Locale.GetText ("missing <mscorlib> tag"));
123 SecurityElement security = (SecurityElement) mscorlib.Children [0];
124 if (security.Tag != "security")
125 throw new ArgumentException (Locale.GetText ("missing <security> tag"));
126 SecurityElement policy = (SecurityElement) security.Children [0];
127 if (policy.Tag != "policy")
128 throw new ArgumentException (Locale.GetText ("missing <policy> tag"));
129 SecurityElement policyLevel = (SecurityElement) policy.Children [0];
130 FromXml (policyLevel);
135 public IList FullTrustAssemblies
137 get { return full_trust_assemblies; }
140 public string Label {
141 get { return label; }
144 public IList NamedPermissionSets {
145 get { return named_permission_sets; }
148 public CodeGroup RootCodeGroup {
149 get { return root_code_group; }
152 throw new ArgumentNullException ("value");
153 root_code_group = value;
157 public string StoreLocation {
158 get { return _location; }
162 public PolicyLevelType Type {
163 get { return _type; }
169 public void AddFullTrustAssembly (StrongName sn)
172 throw new ArgumentNullException ("sn");
174 StrongNameMembershipCondition snMC = new StrongNameMembershipCondition(
175 sn.PublicKey, sn.Name, sn.Version);
177 AddFullTrustAssembly (snMC);
180 public void AddFullTrustAssembly (StrongNameMembershipCondition snMC)
183 throw new ArgumentNullException ("snMC");
185 foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
186 if (sn.Equals (snMC)) {
187 throw new ArgumentException (Locale.GetText ("sn already has full trust."));
190 full_trust_assemblies.Add (snMC);
193 public void AddNamedPermissionSet (NamedPermissionSet permSet)
196 throw new ArgumentNullException ("permSet");
198 foreach (NamedPermissionSet n in named_permission_sets) {
199 if (permSet.Name == n.Name) {
200 throw new ArgumentException (
201 Locale.GetText ("This NamedPermissionSet is the same an existing NamedPermissionSet."));
204 named_permission_sets.Add (permSet.Copy ());
207 public NamedPermissionSet ChangeNamedPermissionSet (string name, PermissionSet pSet)
210 throw new ArgumentNullException ("name");
212 throw new ArgumentNullException ("pSet");
213 if (IsReserved (name))
214 throw new ArgumentException (Locale.GetText ("Reserved name"));
216 foreach (NamedPermissionSet n in named_permission_sets) {
217 if (name == n.Name) {
218 named_permission_sets.Remove (n);
219 AddNamedPermissionSet (new NamedPermissionSet (name, pSet));
223 throw new ArgumentException (Locale.GetText ("PermissionSet not found"));
226 public static PolicyLevel CreateAppDomainLevel ()
228 NamedPermissionSet fullTrust = new NamedPermissionSet ("FullTrust", PermissionState.Unrestricted);
229 UnionCodeGroup cg = new UnionCodeGroup (new AllMembershipCondition (), new PolicyStatement (fullTrust));
230 cg.Name = "All_Code";
231 PolicyLevel pl = new PolicyLevel ("AppDomain", PolicyLevelType.AppDomain);
232 pl.RootCodeGroup = cg;
237 public void FromXml (SecurityElement e)
240 throw new ArgumentNullException ("e");
241 // MS doesn't throw an exception for this case
242 // if (e.Tag != "PolicyLevel")
243 // throw new ArgumentException (Locale.GetText ("Invalid XML"));
245 SecurityElement sc = e.SearchForChildByTag ("SecurityClasses");
246 if ((sc != null) && (sc.Children != null) && (sc.Children.Count > 0)) {
247 fullNames = new Hashtable (sc.Children.Count);
248 foreach (SecurityElement se in sc.Children) {
249 fullNames.Add (se.Attributes ["Name"], se.Attributes ["Description"]);
253 SecurityElement nps = e.SearchForChildByTag ("NamedPermissionSets");
254 if ((nps != null) && (nps.Children != null) && (nps.Children.Count > 0)) {
255 named_permission_sets.Clear ();
256 foreach (SecurityElement se in nps.Children) {
257 NamedPermissionSet n = new NamedPermissionSet ();
260 named_permission_sets.Add (n);
264 SecurityElement cg = e.SearchForChildByTag ("CodeGroup");
265 if ((cg != null) && (cg.Children != null) && (cg.Children.Count > 0)) {
266 root_code_group = CodeGroup.CreateFromXml (cg, this);
269 throw new ArgumentException (Locale.GetText ("Missing Root CodeGroup"));
271 SecurityElement fta = e.SearchForChildByTag ("FullTrustAssemblies");
272 if ((fta != null) && (fta.Children != null) && (fta.Children.Count > 0)) {
273 full_trust_assemblies.Clear ();
274 foreach (SecurityElement se in fta.Children) {
275 if (se.Tag != "IMembershipCondition")
276 throw new ArgumentException (Locale.GetText ("Invalid XML"));
277 string className = se.Attribute ("class");
278 if (className.IndexOf ("StrongNameMembershipCondition") < 0)
279 throw new ArgumentException (Locale.GetText ("Invalid XML - must be StrongNameMembershipCondition"));
280 // we directly use StrongNameMembershipCondition
281 full_trust_assemblies.Add (new StrongNameMembershipCondition (se));
286 public NamedPermissionSet GetNamedPermissionSet (string name)
289 throw new ArgumentNullException ("name");
291 foreach (NamedPermissionSet n in named_permission_sets) {
293 return (NamedPermissionSet) n.Copy ();
299 public void Recover ()
301 throw new NotImplementedException ();
304 public void RemoveFullTrustAssembly (StrongName sn)
307 throw new ArgumentNullException ("sn");
309 StrongNameMembershipCondition s = new StrongNameMembershipCondition (sn.PublicKey, sn.Name, sn.Version);
310 RemoveFullTrustAssembly (s);
313 public void RemoveFullTrustAssembly (StrongNameMembershipCondition snMC)
316 throw new ArgumentNullException ("snMC");
318 if (((IList) full_trust_assemblies).Contains (snMC))
319 ((IList) full_trust_assemblies).Remove (snMC);
322 throw new ArgumentException (
323 Locale.GetText ("sn does not have full trust."));
326 public NamedPermissionSet RemoveNamedPermissionSet (NamedPermissionSet permSet)
329 throw new ArgumentNullException ("permSet");
331 if (! ((IList )named_permission_sets).Contains (permSet))
332 throw new ArgumentException (
333 Locale.GetText ("permSet cannot be found."));
335 ((IList) named_permission_sets).Remove (permSet);
340 [MonoTODO ("Check for reserved names")]
341 public NamedPermissionSet RemoveNamedPermissionSet (string name)
344 throw new ArgumentNullException ("name");
346 foreach (NamedPermissionSet nps in named_permission_sets) {
347 if (name == nps.Name) {
348 named_permission_sets.Remove (nps);
352 string msg = String.Format (Locale.GetText ("Name '{0}' cannot be found."), name);
353 throw new ArgumentException (msg, "name");
358 if (fullNames != null)
360 full_trust_assemblies.Clear ();
361 named_permission_sets.Clear ();
363 if (_type != PolicyLevelType.AppDomain) {
364 // because the policy doesn't exist LoadFromFile will try to
365 // 1. use the .default file if existing (like Fx 2.0 does); or
366 // 2. use the hard-coded default values
367 // and recreate a policy file
368 if ((_location != null) && (File.Exists (_location))) {
370 File.Delete (_location);
374 LoadFromFile (_location);
377 named_permission_sets.Add (new NamedPermissionSet ("LocalIntranet"));
378 named_permission_sets.Add (new NamedPermissionSet ("Internet"));
379 named_permission_sets.Add (new NamedPermissionSet ("SkipVerification"));
380 named_permission_sets.Add (new NamedPermissionSet ("Execution"));
381 named_permission_sets.Add (new NamedPermissionSet ("Nothing"));
382 named_permission_sets.Add (new NamedPermissionSet ("Everything"));
383 named_permission_sets.Add (new NamedPermissionSet ("FullTrust"));
387 public PolicyStatement Resolve (Evidence evidence)
389 if (evidence == null)
390 throw new ArgumentNullException ("evidence");
392 PolicyStatement ps = root_code_group.Resolve (evidence);
393 return ((ps != null) ? ps : PolicyStatement.Empty ());
396 public CodeGroup ResolveMatchingCodeGroups (Evidence evidence)
398 if (evidence == null)
399 throw new ArgumentNullException ("evidence");
401 CodeGroup cg = root_code_group.ResolveMatchingCodeGroups (evidence);
403 return ((cg != null) ? cg : null);
407 public SecurityElement ToXml ()
409 Hashtable fullNames = new Hashtable ();
410 // only StrongNameMembershipCondition so no need to loop
411 if (full_trust_assemblies.Count > 0) {
412 if (!fullNames.Contains ("StrongNameMembershipCondition")) {
413 fullNames.Add ("StrongNameMembershipCondition", typeof (StrongNameMembershipCondition).FullName);
417 SecurityElement namedPSs = new SecurityElement ("NamedPermissionSets");
418 foreach (NamedPermissionSet nps in named_permission_sets) {
419 SecurityElement se = nps.ToXml ();
420 object objectClass = se.Attributes ["class"];
421 if (!fullNames.Contains (objectClass)) {
422 fullNames.Add (objectClass, nps.GetType ().FullName);
424 namedPSs.AddChild (se);
427 SecurityElement fta = new SecurityElement ("FullTrustAssemblies");
428 foreach (StrongNameMembershipCondition snmc in full_trust_assemblies) {
429 fta.AddChild (snmc.ToXml (this));
432 SecurityElement security_classes = new SecurityElement ("SecurityClasses");
433 if (fullNames.Count > 0) {
434 foreach (DictionaryEntry de in fullNames) {
435 SecurityElement sc = new SecurityElement ("SecurityClass");
436 sc.AddAttribute ("Name", (string)de.Key);
437 sc.AddAttribute ("Description", (string)de.Value);
438 security_classes.AddChild (sc);
442 SecurityElement element = new SecurityElement (typeof (System.Security.Policy.PolicyLevel).Name);
443 element.AddAttribute ("version", "1");
444 element.AddChild (security_classes);
445 element.AddChild (namedPSs);
446 if (root_code_group != null) {
447 element.AddChild (root_code_group.ToXml (this));
449 element.AddChild (fta);
456 internal bool IsReserved (string name)
460 case "LocalIntranet":
462 case "SkipVerification":
466 // FIXME: Are there others ?
473 // NOTE: Callers are expected to check for ControlPolicy
474 internal void Save ()
476 if (_type == PolicyLevelType.AppDomain) {
477 throw new PolicyException (Locale.GetText (
478 "Can't save AppDomain PolicyLevel"));
481 if (_location != null) {
482 using (StreamWriter sw = new StreamWriter (_location)) {
483 sw.Write (ToXml ().ToString ());
489 // TODO : hardcode defaults in case
490 // (a) the specified policy file doesn't exists; and
491 // (b) no corresponding default policy file exists
492 internal void CreateFromHardcodedDefault (PolicyLevelType type)
494 PolicyStatement psu = new PolicyStatement (new PermissionSet (PermissionState.Unrestricted));
497 case PolicyLevelType.Machine:
498 // by default all stuff is in the machine policy...
499 root_code_group = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.MyComputer), psu);
500 root_code_group.Name = "All_Code";
502 case PolicyLevelType.User:
503 case PolicyLevelType.Enterprise:
504 case PolicyLevelType.AppDomain:
505 // while the other policies don't restrict anything
506 root_code_group = new UnionCodeGroup (new AllMembershipCondition (), psu);
507 root_code_group.Name = "All_Code";
512 internal string ResolveClassName (string className)
514 if (fullNames != null) {
515 object name = fullNames [className];
517 return (string) name;