2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Security.Policy / PolicyLevel.cs
bloba124af3d3202dd0570c0450508911b6b2d8313ac
1 //
2 // System.Security.Policy.PolicyLevel.cs
3 //
4 // Authors:
5 // Nick Drochak (ndrochak@gol.com)
6 // Duncan Mak (duncan@ximian.com)
7 // Sebastien Pouliot <sebastien@ximian.com>
8 //
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:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
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 #if !MOONLIGHT
36 using System.Collections; // for IList
37 using System.Globalization;
38 using System.IO;
39 using System.Reflection;
40 using System.Runtime.InteropServices;
41 using System.Security.Permissions;
43 using Mono.Xml;
45 namespace System.Security.Policy {
47 [Serializable]
48 [ComVisible (true)]
49 public sealed class PolicyLevel {
51 string label;
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;
58 private SecurityElement xml;
60 internal PolicyLevel (string label, PolicyLevelType type)
62 this.label = label;
63 _type = type;
64 full_trust_assemblies = new ArrayList ();
65 named_permission_sets = new ArrayList ();
68 internal void LoadFromFile (string filename)
70 try {
71 // check for policy file
72 if (!File.Exists (filename)) {
73 // if it doesn't exist use the default configuration (like Fx 2.0)
74 // ref: http://blogs.msdn.com/shawnfa/archive/2004/04/21/117833.aspx
75 string defcfg = filename + ".default";
76 if (File.Exists (defcfg)) {
77 // create policy from default file
78 File.Copy (defcfg, filename);
81 // load security policy configuration
82 if (File.Exists (filename)) {
83 using (StreamReader sr = File.OpenText (filename)) {
84 xml = FromString (sr.ReadToEnd ());
86 try {
87 SecurityManager.ResolvingPolicyLevel = this;
88 FromXml (xml);
90 finally {
91 SecurityManager.ResolvingPolicyLevel = this;
93 } else {
94 CreateDefaultFullTrustAssemblies ();
95 CreateDefaultNamedPermissionSets ();
96 CreateDefaultLevel (_type);
97 Save ();
100 catch {
101 // this can fail in many ways including...
102 // * can't lookup policy (path discovery);
103 // * can't copy default file to policy
104 // * can't read policy file;
105 // * can't decode policy file
106 // * can't save hardcoded policy to filename
108 finally {
109 _location = filename;
113 internal void LoadFromString (string xml)
115 FromXml (FromString (xml));
118 private SecurityElement FromString (string xml)
120 SecurityParser parser = new SecurityParser ();
121 parser.LoadXml (xml);
122 // configuration / mscorlib / security / policy / PolicyLevel
123 SecurityElement configuration = parser.ToXml ();
124 if (configuration.Tag != "configuration")
125 throw new ArgumentException (Locale.GetText ("missing <configuration> root element"));
126 SecurityElement mscorlib = (SecurityElement) configuration.Children [0];
127 if (mscorlib.Tag != "mscorlib")
128 throw new ArgumentException (Locale.GetText ("missing <mscorlib> tag"));
129 SecurityElement security = (SecurityElement) mscorlib.Children [0];
130 if (security.Tag != "security")
131 throw new ArgumentException (Locale.GetText ("missing <security> tag"));
132 SecurityElement policy = (SecurityElement) security.Children [0];
133 if (policy.Tag != "policy")
134 throw new ArgumentException (Locale.GetText ("missing <policy> tag"));
135 SecurityElement policyLevel = (SecurityElement) policy.Children [0];
136 return policyLevel;
139 // properties
141 [Obsolete ("All GACed assemblies are now fully trusted and all permissions now succeed on fully trusted code.")]
142 public IList FullTrustAssemblies {
143 get { return full_trust_assemblies; }
146 public string Label {
147 get { return label; }
150 public IList NamedPermissionSets {
151 get { return named_permission_sets; }
154 public CodeGroup RootCodeGroup {
155 get { return root_code_group; }
156 set {
157 if (value == null)
158 throw new ArgumentNullException ("value");
159 root_code_group = value;
163 public string StoreLocation {
164 get { return _location; }
167 [ComVisible (false)]
168 public PolicyLevelType Type {
169 get { return _type; }
172 // methods
174 [Obsolete ("All GACed assemblies are now fully trusted and all permissions now succeed on fully trusted code.")]
175 public void AddFullTrustAssembly (StrongName sn)
177 if (sn == null)
178 throw new ArgumentNullException ("sn");
180 StrongNameMembershipCondition snMC = new StrongNameMembershipCondition(
181 sn.PublicKey, sn.Name, sn.Version);
183 AddFullTrustAssembly (snMC);
186 [Obsolete ("All GACed assemblies are now fully trusted and all permissions now succeed on fully trusted code.")]
187 public void AddFullTrustAssembly (StrongNameMembershipCondition snMC)
189 if (snMC == null)
190 throw new ArgumentNullException ("snMC");
192 foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
193 if (sn.Equals (snMC)) {
194 throw new ArgumentException (Locale.GetText ("sn already has full trust."));
197 full_trust_assemblies.Add (snMC);
200 public void AddNamedPermissionSet (NamedPermissionSet permSet)
202 if (permSet == null)
203 throw new ArgumentNullException ("permSet");
205 foreach (NamedPermissionSet n in named_permission_sets) {
206 if (permSet.Name == n.Name) {
207 throw new ArgumentException (
208 Locale.GetText ("This NamedPermissionSet is the same an existing NamedPermissionSet."));
211 named_permission_sets.Add (permSet.Copy ());
214 public NamedPermissionSet ChangeNamedPermissionSet (string name, PermissionSet pSet)
216 if (name == null)
217 throw new ArgumentNullException ("name");
218 if (pSet == null)
219 throw new ArgumentNullException ("pSet");
220 if (DefaultPolicies.ReservedNames.IsReserved (name))
221 throw new ArgumentException (Locale.GetText ("Reserved name"));
223 foreach (NamedPermissionSet n in named_permission_sets) {
224 if (name == n.Name) {
225 named_permission_sets.Remove (n);
226 AddNamedPermissionSet (new NamedPermissionSet (name, pSet));
227 return n;
230 throw new ArgumentException (Locale.GetText ("PermissionSet not found"));
233 public static PolicyLevel CreateAppDomainLevel ()
235 UnionCodeGroup cg = new UnionCodeGroup (new AllMembershipCondition (), new PolicyStatement (DefaultPolicies.FullTrust));
236 cg.Name = "All_Code";
237 PolicyLevel pl = new PolicyLevel ("AppDomain", PolicyLevelType.AppDomain);
238 pl.RootCodeGroup = cg;
239 pl.Reset ();
240 return pl;
244 public void FromXml (SecurityElement e)
246 if (e == null)
247 throw new ArgumentNullException ("e");
248 // MS doesn't throw an exception for this case
249 // if (e.Tag != "PolicyLevel")
250 // throw new ArgumentException (Locale.GetText ("Invalid XML"));
252 SecurityElement sc = e.SearchForChildByTag ("SecurityClasses");
253 if ((sc != null) && (sc.Children != null) && (sc.Children.Count > 0)) {
254 fullNames = new Hashtable (sc.Children.Count);
255 foreach (SecurityElement se in sc.Children) {
256 fullNames.Add (se.Attributes ["Name"], se.Attributes ["Description"]);
260 SecurityElement fta = e.SearchForChildByTag ("FullTrustAssemblies");
261 if ((fta != null) && (fta.Children != null) && (fta.Children.Count > 0)) {
262 full_trust_assemblies.Clear ();
263 foreach (SecurityElement se in fta.Children) {
264 if (se.Tag != "IMembershipCondition")
265 throw new ArgumentException (Locale.GetText ("Invalid XML"));
266 string className = se.Attribute ("class");
267 if (className.IndexOf ("StrongNameMembershipCondition") < 0)
268 throw new ArgumentException (Locale.GetText ("Invalid XML - must be StrongNameMembershipCondition"));
269 // we directly use StrongNameMembershipCondition
270 full_trust_assemblies.Add (new StrongNameMembershipCondition (se));
274 SecurityElement cg = e.SearchForChildByTag ("CodeGroup");
275 if ((cg != null) && (cg.Children != null) && (cg.Children.Count > 0)) {
276 root_code_group = CodeGroup.CreateFromXml (cg, this);
277 } else {
278 throw new ArgumentException (Locale.GetText ("Missing Root CodeGroup"));
281 SecurityElement nps = e.SearchForChildByTag ("NamedPermissionSets");
282 if ((nps != null) && (nps.Children != null) && (nps.Children.Count > 0)) {
283 named_permission_sets.Clear ();
284 foreach (SecurityElement se in nps.Children) {
285 NamedPermissionSet n = new NamedPermissionSet ();
286 n.Resolver = this;
287 n.FromXml (se);
288 named_permission_sets.Add (n);
293 public NamedPermissionSet GetNamedPermissionSet (string name)
295 if (name == null)
296 throw new ArgumentNullException ("name");
298 foreach (NamedPermissionSet n in named_permission_sets) {
299 if (n.Name == name)
300 return (NamedPermissionSet) n.Copy ();
302 return null;
305 public void Recover ()
307 if (_location == null) {
308 string msg = Locale.GetText ("Only file based policies may be recovered.");
309 throw new PolicyException (msg);
312 string backup = _location + ".backup";
313 if (!File.Exists (backup)) {
314 string msg = Locale.GetText ("No policy backup exists.");
315 throw new PolicyException (msg);
318 try {
319 File.Copy (backup, _location, true);
321 catch (Exception e) {
322 string msg = Locale.GetText ("Couldn't replace the policy file with it's backup.");
323 throw new PolicyException (msg, e);
327 [Obsolete ("All GACed assemblies are now fully trusted and all permissions now succeed on fully trusted code.")]
328 public void RemoveFullTrustAssembly (StrongName sn)
330 if (sn == null)
331 throw new ArgumentNullException ("sn");
333 StrongNameMembershipCondition s = new StrongNameMembershipCondition (sn.PublicKey, sn.Name, sn.Version);
334 RemoveFullTrustAssembly (s);
337 [Obsolete ("All GACed assemblies are now fully trusted and all permissions now succeed on fully trusted code.")]
338 public void RemoveFullTrustAssembly (StrongNameMembershipCondition snMC)
340 if (snMC == null)
341 throw new ArgumentNullException ("snMC");
343 if (((IList) full_trust_assemblies).Contains (snMC))
344 ((IList) full_trust_assemblies).Remove (snMC);
346 else
347 throw new ArgumentException (
348 Locale.GetText ("sn does not have full trust."));
351 public NamedPermissionSet RemoveNamedPermissionSet (NamedPermissionSet permSet)
353 if (permSet == null)
354 throw new ArgumentNullException ("permSet");
356 return RemoveNamedPermissionSet (permSet.Name);
359 public NamedPermissionSet RemoveNamedPermissionSet (string name)
361 if (name == null)
362 throw new ArgumentNullException ("name");
363 if (DefaultPolicies.ReservedNames.IsReserved (name))
364 throw new ArgumentException (Locale.GetText ("Reserved name"));
366 foreach (NamedPermissionSet nps in named_permission_sets) {
367 if (name == nps.Name) {
368 named_permission_sets.Remove (nps);
369 return nps;
372 string msg = String.Format (Locale.GetText ("Name '{0}' cannot be found."), name);
373 throw new ArgumentException (msg, "name");
376 public void Reset ()
378 if (fullNames != null)
379 fullNames.Clear ();
381 if (_type != PolicyLevelType.AppDomain) {
382 full_trust_assemblies.Clear ();
383 named_permission_sets.Clear ();
385 // because the policy doesn't exist LoadFromFile will try to
386 // 1. use the .default file if existing (like Fx 2.0 does); or
387 // 2. use the hard-coded default values
388 // and recreate a policy file
389 if ((_location != null) && (File.Exists (_location))) {
390 try {
391 File.Delete (_location);
393 catch {}
395 LoadFromFile (_location);
396 } else {
397 CreateDefaultFullTrustAssemblies ();
398 CreateDefaultNamedPermissionSets ();
402 public PolicyStatement Resolve (Evidence evidence)
404 if (evidence == null)
405 throw new ArgumentNullException ("evidence");
407 PolicyStatement ps = root_code_group.Resolve (evidence);
408 return ((ps != null) ? ps : PolicyStatement.Empty ());
411 public CodeGroup ResolveMatchingCodeGroups (Evidence evidence)
413 if (evidence == null)
414 throw new ArgumentNullException ("evidence");
416 CodeGroup cg = root_code_group.ResolveMatchingCodeGroups (evidence);
417 return ((cg != null) ? cg : null);
420 public SecurityElement ToXml ()
422 Hashtable fullNames = new Hashtable ();
423 // only StrongNameMembershipCondition so no need to loop
424 if (full_trust_assemblies.Count > 0) {
425 if (!fullNames.Contains ("StrongNameMembershipCondition")) {
426 fullNames.Add ("StrongNameMembershipCondition", typeof (StrongNameMembershipCondition).FullName);
430 SecurityElement namedPSs = new SecurityElement ("NamedPermissionSets");
431 foreach (NamedPermissionSet nps in named_permission_sets) {
432 SecurityElement se = nps.ToXml ();
433 object objectClass = se.Attributes ["class"];
434 if (!fullNames.Contains (objectClass)) {
435 fullNames.Add (objectClass, nps.GetType ().FullName);
437 namedPSs.AddChild (se);
440 SecurityElement fta = new SecurityElement ("FullTrustAssemblies");
441 foreach (StrongNameMembershipCondition snmc in full_trust_assemblies) {
442 fta.AddChild (snmc.ToXml (this));
445 SecurityElement security_classes = new SecurityElement ("SecurityClasses");
446 if (fullNames.Count > 0) {
447 foreach (DictionaryEntry de in fullNames) {
448 SecurityElement sc = new SecurityElement ("SecurityClass");
449 sc.AddAttribute ("Name", (string)de.Key);
450 sc.AddAttribute ("Description", (string)de.Value);
451 security_classes.AddChild (sc);
455 SecurityElement element = new SecurityElement (typeof (System.Security.Policy.PolicyLevel).Name);
456 element.AddAttribute ("version", "1");
457 element.AddChild (security_classes);
458 element.AddChild (namedPSs);
459 if (root_code_group != null) {
460 element.AddChild (root_code_group.ToXml (this));
462 element.AddChild (fta);
464 return element;
467 // internal stuff
469 // NOTE: Callers are expected to check for ControlPolicy
470 internal void Save ()
472 if (_type == PolicyLevelType.AppDomain) {
473 throw new PolicyException (Locale.GetText (
474 "Can't save AppDomain PolicyLevel"));
477 if (_location != null) {
478 try {
479 if (File.Exists (_location)) {
480 File.Copy (_location, _location + ".backup", true);
483 catch (Exception) {
485 finally {
486 using (StreamWriter sw = new StreamWriter (_location)) {
487 sw.Write (ToXml ().ToString ());
488 sw.Close ();
494 // Hardcode defaults in case
495 // (a) the specified policy file doesn't exists; and
496 // (b) no corresponding default policy file exists
497 internal void CreateDefaultLevel (PolicyLevelType type)
499 PolicyStatement psu = new PolicyStatement (DefaultPolicies.FullTrust);
501 switch (type) {
502 case PolicyLevelType.Machine:
503 // by default all stuff is in the machine policy...
504 PolicyStatement psn = new PolicyStatement (DefaultPolicies.Nothing);
505 root_code_group = new UnionCodeGroup (new AllMembershipCondition (), psn);
506 root_code_group.Name = "All_Code";
508 UnionCodeGroup myComputerZone = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.MyComputer), psu);
509 myComputerZone.Name = "My_Computer_Zone";
510 // TODO: strongname code group for ECMA and MS keys
511 root_code_group.AddChild (myComputerZone);
513 UnionCodeGroup localIntranetZone = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.Intranet),
514 new PolicyStatement (DefaultPolicies.LocalIntranet));
515 localIntranetZone.Name = "LocalIntranet_Zone";
516 // TODO: same site / same directory
517 root_code_group.AddChild (localIntranetZone);
519 PolicyStatement psi = new PolicyStatement (DefaultPolicies.Internet);
520 UnionCodeGroup internetZone = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.Internet), psi);
521 internetZone.Name = "Internet_Zone";
522 // TODO: same site
523 root_code_group.AddChild (internetZone);
525 UnionCodeGroup restrictedZone = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.Untrusted), psn);
526 restrictedZone.Name = "Restricted_Zone";
527 root_code_group.AddChild (restrictedZone);
529 UnionCodeGroup trustedZone = new UnionCodeGroup (new ZoneMembershipCondition (SecurityZone.Trusted), psi);
530 trustedZone.Name = "Trusted_Zone";
531 // TODO: same site
532 root_code_group.AddChild (trustedZone);
533 break;
534 case PolicyLevelType.User:
535 case PolicyLevelType.Enterprise:
536 case PolicyLevelType.AppDomain:
537 // while the other policies don't restrict anything
538 root_code_group = new UnionCodeGroup (new AllMembershipCondition (), psu);
539 root_code_group.Name = "All_Code";
540 break;
544 internal void CreateDefaultFullTrustAssemblies ()
546 // (default) assemblies that are fully trusted during policy resolution
547 full_trust_assemblies.Clear ();
548 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("mscorlib", DefaultPolicies.Key.Ecma));
549 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System", DefaultPolicies.Key.Ecma));
550 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Data", DefaultPolicies.Key.Ecma));
551 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.DirectoryServices", DefaultPolicies.Key.MsFinal));
552 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Drawing", DefaultPolicies.Key.MsFinal));
553 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.Messaging", DefaultPolicies.Key.MsFinal));
554 full_trust_assemblies.Add (DefaultPolicies.FullTrustMembership ("System.ServiceProcess", DefaultPolicies.Key.MsFinal));
557 internal void CreateDefaultNamedPermissionSets ()
559 named_permission_sets.Clear ();
560 try {
561 SecurityManager.ResolvingPolicyLevel = this;
562 named_permission_sets.Add (DefaultPolicies.LocalIntranet);
563 named_permission_sets.Add (DefaultPolicies.Internet);
564 named_permission_sets.Add (DefaultPolicies.SkipVerification);
565 named_permission_sets.Add (DefaultPolicies.Execution);
566 named_permission_sets.Add (DefaultPolicies.Nothing);
567 named_permission_sets.Add (DefaultPolicies.Everything);
568 named_permission_sets.Add (DefaultPolicies.FullTrust);
570 finally {
571 SecurityManager.ResolvingPolicyLevel = null;
575 internal string ResolveClassName (string className)
577 if (fullNames != null) {
578 object name = fullNames [className];
579 if (name != null)
580 return (string) name;
582 return className;
585 internal bool IsFullTrustAssembly (Assembly a)
587 AssemblyName an = a.UnprotectedGetName ();
588 StrongNamePublicKeyBlob snpkb = new StrongNamePublicKeyBlob (an.GetPublicKey ());
589 StrongNameMembershipCondition snMC = new StrongNameMembershipCondition (snpkb, an.Name, an.Version);
590 foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
591 if (sn.Equals (snMC)) {
592 return true;
595 return false;
600 #endif