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-2005 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.Runtime.InteropServices;
39 using System.Security.Permissions;
43 namespace System.Security.Policy {
49 public sealed class PolicyLevel {
52 CodeGroup root_code_group;
53 private ArrayList full_trust_assemblies;
54 private ArrayList named_permission_sets;
55 private string _location;
56 private PolicyLevelType _type;
57 private Hashtable fullNames;
59 private SecurityElement xml;
61 internal PolicyLevel (string label, PolicyLevelType type)
65 full_trust_assemblies = new ArrayList ();
66 named_permission_sets = new ArrayList ();
69 internal void LoadFromFile (string filename)
73 // check for policy file
74 if (!File.Exists (filename)) {
75 // if it doesn't exist use the default configuration (like Fx 2.0)
76 // ref: http://blogs.msdn.com/shawnfa/archive/2004/04/21/117833.aspx
77 string defcfg = filename + ".default";
78 if (File.Exists (defcfg)) {
79 // create policy from default file
80 File.Copy (defcfg, filename);
83 // load security policy configuration
84 if (File.Exists (filename)) {
85 using (StreamReader sr = File.OpenText (filename)) {
86 xml = FromString (sr.ReadToEnd ());
91 CreateDefaultLevel (_type);
95 // this can fail in many ways including...
96 // * can't lookup policy (path discovery);
97 // * can't copy default file to policy
98 // * can't read policy file;
99 // * can't decode policy file
101 CreateDefaultLevel (_type);
104 _location = filename;
108 internal void Initialize ()
113 CreateDefaultNamedPermissionSets ();
118 // this can fail in many ways including...
119 // * can't save hardcoded policy to filename
124 internal void LoadFromString (string xml)
126 FromXml (FromString (xml));
129 private SecurityElement FromString (string xml)
131 SecurityParser parser = new SecurityParser ();
132 parser.LoadXml (xml);
133 // configuration / mscorlib / security / policy / PolicyLevel
134 SecurityElement configuration = parser.ToXml ();
135 if (configuration.Tag != "configuration")
136 throw new ArgumentException (Locale.GetText ("missing <configuration> root element"));
137 SecurityElement mscorlib = (SecurityElement) configuration.Children [0];
138 if (mscorlib.Tag != "mscorlib")
139 throw new ArgumentException (Locale.GetText ("missing <mscorlib> tag"));
140 SecurityElement security = (SecurityElement) mscorlib.Children [0];
141 if (security.Tag != "security")
142 throw new ArgumentException (Locale.GetText ("missing <security> tag"));
143 SecurityElement policy = (SecurityElement) security.Children [0];
144 if (policy.Tag != "policy")
145 throw new ArgumentException (Locale.GetText ("missing <policy> tag"));
146 SecurityElement policyLevel = (SecurityElement) policy.Children [0];
152 public IList FullTrustAssemblies {
153 get { return full_trust_assemblies; }
156 public string Label {
157 get { return label; }
160 public IList NamedPermissionSets {
161 get { return named_permission_sets; }
164 public CodeGroup RootCodeGroup {
165 get { return root_code_group; }
168 throw new ArgumentNullException ("value");
169 root_code_group = value;
173 public string StoreLocation {
174 get { return _location; }
179 public PolicyLevelType Type {
180 get { return _type; }
186 public void AddFullTrustAssembly (StrongName sn)
189 throw new ArgumentNullException ("sn");
191 StrongNameMembershipCondition snMC = new StrongNameMembershipCondition(
192 sn.PublicKey, sn.Name, sn.Version);
194 AddFullTrustAssembly (snMC);
197 public void AddFullTrustAssembly (StrongNameMembershipCondition snMC)
200 throw new ArgumentNullException ("snMC");
202 foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
203 if (sn.Equals (snMC)) {
204 throw new ArgumentException (Locale.GetText ("sn already has full trust."));
207 full_trust_assemblies.Add (snMC);
210 public void AddNamedPermissionSet (NamedPermissionSet permSet)
213 throw new ArgumentNullException ("permSet");
215 foreach (NamedPermissionSet n in named_permission_sets) {
216 if (permSet.Name == n.Name) {
217 throw new ArgumentException (
218 Locale.GetText ("This NamedPermissionSet is the same an existing NamedPermissionSet."));
221 named_permission_sets.Add (permSet.Copy ());
224 public NamedPermissionSet ChangeNamedPermissionSet (string name, PermissionSet pSet)
227 throw new ArgumentNullException ("name");
229 throw new ArgumentNullException ("pSet");
230 if (DefaultPolicies.ReservedNames.IsReserved (name))
231 throw new ArgumentException (Locale.GetText ("Reserved name"));
233 foreach (NamedPermissionSet n in named_permission_sets) {
234 if (name == n.Name) {
235 named_permission_sets.Remove (n);
236 AddNamedPermissionSet (new NamedPermissionSet (name, pSet));
240 throw new ArgumentException (Locale.GetText ("PermissionSet not found"));
243 public static PolicyLevel CreateAppDomainLevel ()
245 NamedPermissionSet fullTrust = new NamedPermissionSet ("FullTrust", PermissionState.Unrestricted);
246 UnionCodeGroup cg = new UnionCodeGroup (new AllMembershipCondition (), new PolicyStatement (fullTrust));
247 cg.Name = "All_Code";
248 PolicyLevel pl = new PolicyLevel ("AppDomain", PolicyLevelType.AppDomain);
249 pl.RootCodeGroup = cg;
255 public void FromXml (SecurityElement e)
258 throw new ArgumentNullException ("e");
259 // MS doesn't throw an exception for this case
260 // if (e.Tag != "PolicyLevel")
261 // throw new ArgumentException (Locale.GetText ("Invalid XML"));
267 internal void FromXml1 (SecurityElement e)
269 SecurityElement sc = e.SearchForChildByTag ("SecurityClasses");
270 if ((sc != null) && (sc.Children != null) && (sc.Children.Count > 0)) {
271 fullNames = new Hashtable (sc.Children.Count);
272 foreach (SecurityElement se in sc.Children) {
273 fullNames.Add (se.Attributes ["Name"], se.Attributes ["Description"]);
277 SecurityElement fta = e.SearchForChildByTag ("FullTrustAssemblies");
278 if ((fta != null) && (fta.Children != null) && (fta.Children.Count > 0)) {
279 full_trust_assemblies.Clear ();
280 foreach (SecurityElement se in fta.Children) {
281 if (se.Tag != "IMembershipCondition")
282 throw new ArgumentException (Locale.GetText ("Invalid XML"));
283 string className = se.Attribute ("class");
284 if (className.IndexOf ("StrongNameMembershipCondition") < 0)
285 throw new ArgumentException (Locale.GetText ("Invalid XML - must be StrongNameMembershipCondition"));
286 // we directly use StrongNameMembershipCondition
287 full_trust_assemblies.Add (new StrongNameMembershipCondition (se));
291 SecurityElement cg = e.SearchForChildByTag ("CodeGroup");
292 if ((cg != null) && (cg.Children != null) && (cg.Children.Count > 0)) {
293 root_code_group = CodeGroup.CreateFromXml (cg, this);
296 throw new ArgumentException (Locale.GetText ("Missing Root CodeGroup"));
299 internal void FromXml2 (SecurityElement e)
301 SecurityElement nps = e.SearchForChildByTag ("NamedPermissionSets");
302 if ((nps != null) && (nps.Children != null) && (nps.Children.Count > 0)) {
303 named_permission_sets.Clear ();
304 foreach (SecurityElement se in nps.Children) {
305 NamedPermissionSet n = new NamedPermissionSet ();
308 named_permission_sets.Add (n);
313 public NamedPermissionSet GetNamedPermissionSet (string name)
316 throw new ArgumentNullException ("name");
318 foreach (NamedPermissionSet n in named_permission_sets) {
320 return (NamedPermissionSet) n.Copy ();
325 public void Recover ()
327 if (_location == null) {
328 string msg = Locale.GetText ("Only file based policies may be recovered.");
329 throw new PolicyException (msg);
332 string backup = _location + ".backup";
333 if (!File.Exists (backup)) {
334 string msg = Locale.GetText ("No policy backup exists.");
335 throw new PolicyException (msg);
339 File.Copy (backup, _location, true);
341 catch (Exception e) {
342 string msg = Locale.GetText ("Couldn't replace the policy file with it's backup.");
343 throw new PolicyException (msg, e);
347 public void RemoveFullTrustAssembly (StrongName sn)
350 throw new ArgumentNullException ("sn");
352 StrongNameMembershipCondition s = new StrongNameMembershipCondition (sn.PublicKey, sn.Name, sn.Version);
353 RemoveFullTrustAssembly (s);
356 public void RemoveFullTrustAssembly (StrongNameMembershipCondition snMC)
359 throw new ArgumentNullException ("snMC");
361 if (((IList) full_trust_assemblies).Contains (snMC))
362 ((IList) full_trust_assemblies).Remove (snMC);
365 throw new ArgumentException (
366 Locale.GetText ("sn does not have full trust."));
369 public NamedPermissionSet RemoveNamedPermissionSet (NamedPermissionSet permSet)
372 throw new ArgumentNullException ("permSet");
374 return RemoveNamedPermissionSet (permSet.Name);
377 public NamedPermissionSet RemoveNamedPermissionSet (string name)
380 throw new ArgumentNullException ("name");
381 if (DefaultPolicies.ReservedNames.IsReserved (name))
382 throw new ArgumentException (Locale.GetText ("Reserved name"));
384 foreach (NamedPermissionSet nps in named_permission_sets) {
385 if (name == nps.Name) {
386 named_permission_sets.Remove (nps);
390 string msg = String.Format (Locale.GetText ("Name '{0}' cannot be found."), name);
391 throw new ArgumentException (msg, "name");
396 if (fullNames != null)
398 full_trust_assemblies.Clear ();
399 named_permission_sets.Clear ();
401 if (_type != PolicyLevelType.AppDomain) {
402 // because the policy doesn't exist LoadFromFile will try to
403 // 1. use the .default file if existing (like Fx 2.0 does); or
404 // 2. use the hard-coded default values
405 // and recreate a policy file
406 if ((_location != null) && (File.Exists (_location))) {
408 File.Delete (_location);
412 LoadFromFile (_location);
415 named_permission_sets.Add (DefaultPolicies.LocalIntranet);
416 named_permission_sets.Add (DefaultPolicies.Internet);
417 named_permission_sets.Add (DefaultPolicies.SkipVerification);
418 named_permission_sets.Add (DefaultPolicies.Execution);
419 named_permission_sets.Add (DefaultPolicies.Nothing);
420 named_permission_sets.Add (DefaultPolicies.Everything);
421 named_permission_sets.Add (DefaultPolicies.FullTrust);
425 public PolicyStatement Resolve (Evidence evidence)
427 if (evidence == null)
428 throw new ArgumentNullException ("evidence");
430 PolicyStatement ps = root_code_group.Resolve (evidence);
431 return ((ps != null) ? ps : PolicyStatement.Empty ());
434 public CodeGroup ResolveMatchingCodeGroups (Evidence evidence)
436 if (evidence == null)
437 throw new ArgumentNullException ("evidence");
439 CodeGroup cg = root_code_group.ResolveMatchingCodeGroups (evidence);
441 return ((cg != null) ? cg : null);
445 public SecurityElement ToXml ()
447 Hashtable fullNames = new Hashtable ();
448 // only StrongNameMembershipCondition so no need to loop
449 if (full_trust_assemblies.Count > 0) {
450 if (!fullNames.Contains ("StrongNameMembershipCondition")) {
451 fullNames.Add ("StrongNameMembershipCondition", typeof (StrongNameMembershipCondition).FullName);
455 SecurityElement namedPSs = new SecurityElement ("NamedPermissionSets");
456 foreach (NamedPermissionSet nps in named_permission_sets) {
457 SecurityElement se = nps.ToXml ();
458 object objectClass = se.Attributes ["class"];
459 if (!fullNames.Contains (objectClass)) {
460 fullNames.Add (objectClass, nps.GetType ().FullName);
462 namedPSs.AddChild (se);
465 SecurityElement fta = new SecurityElement ("FullTrustAssemblies");
466 foreach (StrongNameMembershipCondition snmc in full_trust_assemblies) {
467 fta.AddChild (snmc.ToXml (this));
470 SecurityElement security_classes = new SecurityElement ("SecurityClasses");
471 if (fullNames.Count > 0) {
472 foreach (DictionaryEntry de in fullNames) {
473 SecurityElement sc = new SecurityElement ("SecurityClass");
474 sc.AddAttribute ("Name", (string)de.Key);
475 sc.AddAttribute ("Description", (string)de.Value);
476 security_classes.AddChild (sc);
480 SecurityElement element = new SecurityElement (typeof (System.Security.Policy.PolicyLevel).Name);
481 element.AddAttribute ("version", "1");
482 element.AddChild (security_classes);
483 element.AddChild (namedPSs);
484 if (root_code_group != null) {
485 element.AddChild (root_code_group.ToXml (this));
487 element.AddChild (fta);
494 // NOTE: Callers are expected to check for ControlPolicy
495 internal void Save ()
497 if (_type == PolicyLevelType.AppDomain) {
498 throw new PolicyException (Locale.GetText (
499 "Can't save AppDomain PolicyLevel"));
502 if (_location != null) {
504 if (File.Exists (_location)) {
505 File.Copy (_location, _location + ".backup", true);
511 using (StreamWriter sw = new StreamWriter (_location)) {
512 sw.Write (ToXml ().ToString ());
519 // Hardcode defaults in case
520 // (a) the specified policy file doesn't exists; and
521 // (b) no corresponding default policy file exists
522 internal void CreateDefaultLevel (PolicyLevelType type)
524 PolicyStatement psu = new PolicyStatement (new PermissionSet (PermissionState.Unrestricted));
527 case PolicyLevelType.Machine:
528 // by default all stuff is in the machine policy...
529 root_code_group = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.MyComputer), psu);
530 root_code_group.Name = "All_Code";
532 case PolicyLevelType.User:
533 case PolicyLevelType.Enterprise:
534 case PolicyLevelType.AppDomain:
535 // while the other policies don't restrict anything
536 root_code_group = new UnionCodeGroup (new AllMembershipCondition (), psu);
537 root_code_group.Name = "All_Code";
541 // (default) assemblies that are fully trusted during policy resolution
542 full_trust_assemblies.Clear ();
543 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("mscorlib", DefaultPolicies.Key.Ecma));
544 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System", DefaultPolicies.Key.Ecma));
545 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Data", DefaultPolicies.Key.Ecma));
546 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.DirectoryServices", DefaultPolicies.Key.MsFinal));
547 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Drawing", DefaultPolicies.Key.Ecma));
548 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Messaging", DefaultPolicies.Key.MsFinal));
549 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.ServiceProcess", DefaultPolicies.Key.MsFinal));
552 internal void CreateDefaultNamedPermissionSets ()
554 named_permission_sets.Clear ();
555 named_permission_sets.Add (DefaultPolicies.LocalIntranet);
556 named_permission_sets.Add (DefaultPolicies.Internet);
557 named_permission_sets.Add (DefaultPolicies.SkipVerification);
558 named_permission_sets.Add (DefaultPolicies.Execution);
559 named_permission_sets.Add (DefaultPolicies.Nothing);
560 named_permission_sets.Add (DefaultPolicies.Everything);
561 named_permission_sets.Add (DefaultPolicies.FullTrust);
564 internal string ResolveClassName (string className)
566 if (fullNames != null) {
567 object name = fullNames [className];
569 return (string) name;
574 internal bool IsFullTrustAssembly (Assembly a)
576 AssemblyName an = a.GetName ();
577 StrongNamePublicKeyBlob snpkb = new StrongNamePublicKeyBlob (an.GetPublicKey ());
578 StrongNameMembershipCondition snMC = new StrongNameMembershipCondition (snpkb, an.Name, an.Version);
579 foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
580 if (sn.Equals (snMC)) {