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