2004-01-26 Sebastien Pouliot <spouliot@videotron.ca>
[mono.git] / mcs / class / corlib / System.Security.Policy / PolicyLevel.cs
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 (spouliot@motus.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 //
13
14 using System.Collections; // for IList
15 using System.Globalization;
16 using System.IO;
17 using System.Reflection;
18 using System.Security;
19 using System.Security.Permissions;
20
21 using Mono.Xml;
22
23 namespace System.Security.Policy {
24
25         [Serializable]
26         public sealed class PolicyLevel {
27
28                 string label;
29                 CodeGroup root_code_group;
30                 private ArrayList full_trust_assemblies;
31                 private ArrayList named_permission_sets;
32                 private string _location;
33
34                 internal PolicyLevel (string label)
35                 {
36                         this.label = label;
37                         full_trust_assemblies = new ArrayList ();
38                         named_permission_sets = new ArrayList ();
39                 }
40
41                 internal void LoadFromFile (string filename) 
42                 {
43                         if (!File.Exists (filename))
44                                 throw new ArgumentException (Locale.GetText ("file do not exist"));
45                         
46                         // throw a SecurityException if we don't have Read, Write and PathDiscovery permissions
47                         FileIOPermissionAccess access = FileIOPermissionAccess.Read | FileIOPermissionAccess.Write | FileIOPermissionAccess.PathDiscovery;
48                         new FileIOPermission (access, filename).Demand ();
49
50                         using (StreamReader sr = File.OpenText (filename)) {
51                                 string xml = sr.ReadToEnd ();
52                                 LoadFromString (xml);
53                         }
54                         _location = filename;
55                 }
56
57                 internal void LoadFromString (string xml) 
58                 {
59                         SecurityParser parser = new SecurityParser ();
60                         parser.LoadXml (xml);
61                         // configuration / mscorlib / security / policy / PolicyLevel
62                         SecurityElement configuration = parser.ToXml ();
63                         if (configuration.Tag != "configuration")
64                                 throw new ArgumentException (Locale.GetText ("missing <configuration> root element"));
65                         SecurityElement mscorlib = (SecurityElement) configuration.Children [0];
66                         if (mscorlib.Tag != "mscorlib")
67                                 throw new ArgumentException (Locale.GetText ("missing <mscorlib> tag"));
68                         SecurityElement security = (SecurityElement) mscorlib.Children [0];
69                         if (security.Tag != "security")
70                                 throw new ArgumentException (Locale.GetText ("missing <security> tag"));
71                         SecurityElement policy = (SecurityElement) security.Children [0];
72                         if (policy.Tag != "policy")
73                                 throw new ArgumentException (Locale.GetText ("missing <policy> tag"));
74                         SecurityElement policyLevel = (SecurityElement) policy.Children [0];
75                         FromXml (policyLevel);
76                 }
77
78                 // properties
79
80                 public IList FullTrustAssemblies
81                 {
82                         get { return full_trust_assemblies; }
83                 }
84
85                 public string Label {
86                         get { return label; }
87                 }
88
89                 public IList NamedPermissionSets {
90                         get { return named_permission_sets; }
91                 }
92
93                 public CodeGroup RootCodeGroup {
94                         get { return root_code_group; }
95                         set { 
96                                 if (value == null)
97                                         throw new ArgumentNullException ("value");
98                                 root_code_group = value; 
99                         }
100                 }
101
102                 public string StoreLocation {
103                         get { return _location; }
104                 }
105
106                 public void AddFullTrustAssembly (StrongName sn)
107                 {
108                         if (sn == null)
109                                 throw new ArgumentNullException ("sn");
110
111                         StrongNameMembershipCondition snMC = new StrongNameMembershipCondition(
112                                 sn.PublicKey, sn.Name, sn.Version);
113
114                         AddFullTrustAssembly (snMC);
115                 }
116
117                 public void AddFullTrustAssembly (StrongNameMembershipCondition snMC)
118                 {
119                         if (snMC == null)
120                                 throw new ArgumentNullException ("snMC");
121                         
122                         foreach (StrongNameMembershipCondition sn in full_trust_assemblies) {
123                                 if (sn.Equals (snMC)) {
124                                         throw new ArgumentException (Locale.GetText ("sn already has full trust."));
125                                 }
126                         }
127                         full_trust_assemblies.Add (snMC);
128                 }
129
130                 public void AddNamedPermissionSet (NamedPermissionSet permSet)
131                 {
132                         if (permSet == null)
133                                 throw new ArgumentNullException ("permSet");
134
135                         foreach (NamedPermissionSet n in named_permission_sets) {
136                                 if (permSet.Name == n.Name) {
137                                         throw new ArgumentException (
138                                                 Locale.GetText ("This NamedPermissionSet is the same an existing NamedPermissionSet."));
139                                 }
140                         }
141                         named_permission_sets.Add (permSet);
142                 }
143
144                 public NamedPermissionSet ChangeNamedPermissionSet (string name, PermissionSet pSet)
145                 {
146                         if (name == null)
147                                 throw new ArgumentNullException ("name");
148                         if (pSet == null)
149                                 throw new ArgumentNullException ("pSet");
150                         if (IsReserved (name))
151                                 throw new ArgumentException (Locale.GetText ("Reserved name"));
152
153                         foreach (NamedPermissionSet n in named_permission_sets) {
154                                 if (name == n.Name) {
155                                         named_permission_sets.Remove (n);
156                                         AddNamedPermissionSet (new NamedPermissionSet (name, pSet));
157                                         return n;
158                                 }
159                         }
160                         throw new ArgumentException (Locale.GetText ("PermissionSet not found"));
161                 }
162
163                 public static PolicyLevel CreateAppDomainLevel ()
164                 {
165                         NamedPermissionSet fullTrust = new NamedPermissionSet ("FullTrust", PermissionState.Unrestricted);
166                         UnionCodeGroup cg = new UnionCodeGroup (new AllMembershipCondition (), new PolicyStatement (fullTrust));
167                         cg.Name = "All_Code";
168                         PolicyLevel pl = new PolicyLevel ("AppDomain");
169                         pl.RootCodeGroup = cg;
170                         return pl;
171                 }
172
173                 public void FromXml (SecurityElement e)
174                 {
175                         if (e == null)
176                                 throw new ArgumentNullException ("e");
177 // MS doesn't throw an exception for this case
178 //                      if (e.Tag != "PolicyLevel")
179 //                              throw new ArgumentException (Locale.GetText ("Invalid XML"));
180
181                         Hashtable fullNames = null;
182                         SecurityElement sc = e.SearchForChildByTag ("SecurityClasses");
183                         if ((sc != null) && (sc.Children != null) && (sc.Children.Count > 0)) {
184                                 fullNames = new Hashtable (sc.Children.Count);
185                                 foreach (SecurityElement se in sc.Children) {
186                                         fullNames.Add (se.Attributes ["Name"], se.Attributes ["Description"]);
187                                 }
188                         }
189
190                         SecurityElement nps = e.SearchForChildByTag ("NamedPermissionSets");
191                         if ((nps != null) && (nps.Children != null) && (nps.Children.Count > 0)) {
192                                 named_permission_sets.Clear ();
193                                 foreach (SecurityElement se in nps.Children) {
194                                         named_permission_sets.Add (new NamedPermissionSet (se));
195                                 }
196                         }
197
198                         SecurityElement cg = e.SearchForChildByTag ("CodeGroup");
199                         if ((cg != null) && (cg.Children != null) && (cg.Children.Count > 0)) {
200                                 root_code_group = CodeGroup.CreateFromXml (cg);
201                         }
202                         else
203                                 throw new ArgumentException (Locale.GetText ("Missing Root CodeGroup"));
204
205                         SecurityElement fta = e.SearchForChildByTag ("FullTrustAssemblies");
206                         if ((fta != null) && (fta.Children != null) && (fta.Children.Count > 0)) {
207                                 full_trust_assemblies.Clear ();
208                                 foreach (SecurityElement se in fta.Children) {
209                                         if (se.Tag != "IMembershipCondition")
210                                                 throw new ArgumentException (Locale.GetText ("Invalid XML"));
211                                         string className = (string) se.Attributes ["class"];
212                                         if (className.IndexOf ("StrongNameMembershipCondition") < 0)
213                                                 throw new ArgumentException (Locale.GetText ("Invalid XML - must be StrongNameMembershipCondition"));
214                                         // we directly use StrongNameMembershipCondition
215                                         full_trust_assemblies.Add (new StrongNameMembershipCondition (se));
216                                 }
217                         }
218                 }
219
220                 public NamedPermissionSet GetNamedPermissionSet (string name)
221                 {
222                         if (name == null)
223                                 throw new ArgumentNullException ("name");
224
225                         foreach (NamedPermissionSet n in named_permission_sets)
226                                 if (n.Name == name)
227                                         return n;
228
229                         return null;
230                 }
231
232                 [MonoTODO]
233                 public void Recover ()
234                 {
235                         throw new NotImplementedException ();
236                 }
237
238                 public void RemoveFullTrustAssembly (StrongName sn)
239                 {
240                         if (sn == null)
241                                 throw new ArgumentNullException ("sn");
242
243                         StrongNameMembershipCondition s = new StrongNameMembershipCondition (sn.PublicKey, sn.Name, sn.Version);
244                         RemoveFullTrustAssembly (s);
245                 }
246
247                 public void RemoveFullTrustAssembly (StrongNameMembershipCondition snMC)
248                 {
249                         if (snMC == null)
250                                 throw new ArgumentNullException ("snMC");
251
252                         if (((IList) full_trust_assemblies).Contains (snMC))
253                                 ((IList) full_trust_assemblies).Remove (snMC);
254
255                         else
256                                 throw new ArgumentException (
257                                         Locale.GetText ("sn does not have full trust."));
258                 }
259
260                 public NamedPermissionSet RemoveNamedPermissionSet (NamedPermissionSet permSet)
261                 {
262                         if (permSet == null)
263                                 throw new ArgumentNullException (
264                                         Locale.GetText ("The Argument is null."));
265
266                         if (! ((IList )named_permission_sets).Contains (permSet))
267                                 throw new ArgumentException (
268                                         Locale.GetText ("permSet cannot be found."));
269
270                         ((IList) named_permission_sets).Remove (permSet);
271
272                         return permSet;
273                 }
274
275                 [MonoTODO ("Check for reserver names")]
276                 public NamedPermissionSet RemoveNamedPermissionSet (string name)
277                 {
278                         if (name == null)
279                                 throw new ArgumentNullException ("name");
280
281                         int idx = -1;
282                         for (int i = 0; i < named_permission_sets.Count; i++) {
283                                 NamedPermissionSet current = (NamedPermissionSet) named_permission_sets [i];
284
285                                 if (current.Name == name)
286                                         idx = i;
287                                 i ++;
288                         }                       
289
290                         if (idx == -1)
291                                 throw new ArgumentException (
292                                         Locale.GetText ("Name cannot be found."));
293
294                         NamedPermissionSet retval = (NamedPermissionSet) named_permission_sets [idx];
295                         named_permission_sets.RemoveAt (idx);
296
297                         return retval;
298                 }
299
300                 [MonoTODO ("Find out what the default state is")]
301                 public void Reset ()
302                 {
303                         throw new NotImplementedException ();
304                 }
305
306                 [MonoTODO]
307                 public PolicyStatement Resolve (Evidence evidence)
308                 {
309                         if (evidence == null)
310                                 throw new ArgumentNullException ("evidence");
311
312                         throw new NotImplementedException ();
313                 }
314
315                 [MonoTODO]
316                 public CodeGroup ResolveMatchingCodeGroups (Evidence evidence)
317                 {
318                         if (evidence == null)
319                                 throw new ArgumentNullException ("evidence");
320
321                         throw new NotImplementedException ();
322                 }
323
324                 public SecurityElement ToXml ()
325                 {
326                         Hashtable fullNames = new Hashtable ();
327                         // only StrongNameMembershipCondition so no need to loop
328                         if (full_trust_assemblies.Count > 0) {
329                                 if (!fullNames.Contains ("StrongNameMembershipCondition")) {
330                                         fullNames.Add ("StrongNameMembershipCondition", typeof (StrongNameMembershipCondition).FullName);
331                                 }
332                         }
333                         
334                         SecurityElement namedPSs = new SecurityElement ("NamedPermissionSets");
335                         foreach (NamedPermissionSet nps in named_permission_sets) {
336                                 SecurityElement se = nps.ToXml ();
337                                 object objectClass = se.Attributes ["class"];
338                                 if (!fullNames.Contains (objectClass)) {
339                                         fullNames.Add (objectClass, nps.GetType ().FullName);
340                                 }
341                                 namedPSs.AddChild (se);
342                         }
343
344                         SecurityElement fta = new SecurityElement ("FullTrustAssemblies");
345                         foreach (StrongNameMembershipCondition snmc in full_trust_assemblies) {
346                                 fta.AddChild (snmc.ToXml (this));
347                         }
348
349                         SecurityElement security_classes = new SecurityElement ("SecurityClasses");
350                         if (fullNames.Count > 0) {
351                                 foreach (DictionaryEntry de in fullNames) {
352                                         SecurityElement sc = new SecurityElement ("SecurityClass");
353                                         sc.AddAttribute ("Name", (string)de.Key);
354                                         sc.AddAttribute ("Description", (string)de.Value);
355                                         security_classes.AddChild (sc);
356                                 }
357                         }
358
359                         SecurityElement element = new SecurityElement (typeof (System.Security.Policy.PolicyLevel).Name);
360                         element.AddAttribute ("version", "1");
361                         element.AddChild (security_classes);
362                         element.AddChild (namedPSs);
363                         if (root_code_group != null) {
364                                 element.AddChild (root_code_group.ToXml (this));
365                         }
366                         element.AddChild (fta);
367
368                         return element;
369                 }
370
371                 // internal stuff
372
373                 internal bool IsReserved (string name) 
374                 {
375                         switch (name) {
376                                 case "FullTrust":
377                                 case "LocalIntranet":
378                                 case "Internet":
379                                 case "SkipVerification":
380                                 case "Execution":
381                                 case "Nothing":
382                                 case "Everything":
383                                         // FIXME: Are there others ?
384                                         return true;
385                                 default:
386                                         return false;
387                         }
388                 }
389         }
390 }