2004-08-08 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Policy / Evidence.cs
1 //
2 // System.Security.Policy.Evidence
3 //
4 // Authors:
5 //      Sean MacIsaac (macisaac@ximian.com)
6 //      Nick Drochak (ndrochak@gol.com)
7 //      Jackson Harper (Jackson@LatitudeGeo.com)
8 //      Sebastien Pouliot  <sebastien@ximian.com>
9 //
10 // (C) 2001 Ximian, Inc.
11 // Portions (C) 2003, 2004 Motus Technologies Inc. (http://www.motus.com)
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
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.
32 //
33
34 using System;
35 using System.Collections;
36 using System.Reflection;
37 using System.Security.Permissions;
38 using System.Security.Cryptography.X509Certificates;
39
40 namespace System.Security.Policy {
41
42         [Serializable]
43         [MonoTODO ("Fix serialization compatibility with MS.NET")]
44         public sealed class Evidence : ICollection, IEnumerable {
45         
46                 private bool _locked;
47                 private ArrayList hostEvidenceList;     
48                 private ArrayList assemblyEvidenceList;
49                 private int _hashCode;
50
51                 public Evidence () 
52                 {
53                         hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
54                         assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
55                 }
56
57                 public Evidence (Evidence evidence) : this ()
58                 {
59                         if (evidence != null)
60                                 Merge (evidence);       
61                 }
62
63                 public Evidence (object[] hostEvidence, object[] assemblyEvidence) : this ()
64                 {
65                         if (null != hostEvidence)
66                                 hostEvidenceList.AddRange (hostEvidence);
67                         if (null != assemblyEvidence)
68                                 assemblyEvidenceList.AddRange (assemblyEvidence);
69                 }
70                 
71                 //
72                 // Public Properties
73                 //
74         
75                 public int Count {
76                         get {
77                                 return (hostEvidenceList.Count + assemblyEvidenceList.Count);
78                         }
79                 }
80
81                 public bool IsReadOnly {
82                         get{ return false; }
83                 }
84                 
85                 // LAMESPEC: Always TRUE (not FALSE)
86                 public bool IsSynchronized {
87                         get { return true; }
88                 }
89
90                 public bool Locked {
91                         get { return _locked; }
92                         set { 
93                                 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
94                                 _locked = value; 
95                         }
96                 }       
97
98                 public object SyncRoot {
99                         get { return this; }
100                 }
101
102                 //
103                 // Public Methods
104                 //
105
106                 public void AddAssembly (object id) 
107                 {
108                         assemblyEvidenceList.Add (id);
109                         _hashCode = 0;
110                 }
111
112                 public void AddHost (object id) 
113                 {
114                         if (_locked) {
115                                 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
116                         }
117                         hostEvidenceList.Add (id);
118                         _hashCode = 0;
119                 }
120
121 #if NET_2_0
122                 public void Clear ()
123                 {
124                         hostEvidenceList.Clear ();
125                         assemblyEvidenceList.Clear ();
126                         _hashCode = 0;
127                 }
128 #endif
129
130                 public void CopyTo (Array array, int index) 
131                 {
132                         if (hostEvidenceList.Count > 0) 
133                                 hostEvidenceList.CopyTo (array, index);
134                         if (assemblyEvidenceList.Count > 0) 
135                                 assemblyEvidenceList.CopyTo (array, index + hostEvidenceList.Count);
136                 }
137
138 #if NET_2_0
139                 public override bool Equals (object obj)
140                 {
141                         if (obj == null)
142                                 return false;
143                         Evidence e = (obj as Evidence);
144                         if (e == null)
145                                 return false;
146
147                         if (hostEvidenceList.Count != e.hostEvidenceList.Count)
148                                 return false;
149                         if (assemblyEvidenceList.Count != e.assemblyEvidenceList.Count)
150                                 return false;
151
152                         for (int i = 0; i < hostEvidenceList.Count; i++) {
153                                 bool found = false;
154                                 for (int j = 0; j < e.hostEvidenceList.Count; i++) {
155                                         if (hostEvidenceList [i].Equals (e.hostEvidenceList [j])) {
156                                                 found = true;
157                                                 break;
158                                         }
159                                 }
160                                 if (!found)
161                                         return false;
162                         }
163                         for (int i = 0; i < assemblyEvidenceList.Count; i++) {
164                                 bool found = false;
165                                 for (int j = 0; j < e.assemblyEvidenceList.Count; i++) {
166                                         if (assemblyEvidenceList [i].Equals (e.assemblyEvidenceList [j])) {
167                                                 found = true;
168                                                 break;
169                                         }
170                                 }
171                                 if (!found)
172                                         return false;
173                         }
174                         
175                         return true;
176                 }
177 #endif
178
179                 public IEnumerator GetEnumerator () 
180                 {
181                         return new EvidenceEnumerator (hostEvidenceList.GetEnumerator (), 
182                                 assemblyEvidenceList.GetEnumerator ());
183                 }
184
185                 public IEnumerator GetAssemblyEnumerator () 
186                 {
187                         return assemblyEvidenceList.GetEnumerator ();
188                 }
189
190 #if NET_2_0
191                 public override int GetHashCode ()
192                 {
193                         // kind of long so we cache it
194                         if (_hashCode == 0) {
195                                 for (int i = 0; i < hostEvidenceList.Count; i++)
196                                         _hashCode ^= hostEvidenceList [i].GetHashCode ();
197                                 for (int i = 0; i < assemblyEvidenceList.Count; i++)
198                                         _hashCode ^= assemblyEvidenceList [i].GetHashCode ();
199                         }
200                         return _hashCode;
201                 }
202 #endif
203
204                 public IEnumerator GetHostEnumerator () 
205                 {
206                         return hostEvidenceList.GetEnumerator ();
207                 }
208
209                 public void Merge (Evidence evidence) 
210                 {
211                         IEnumerator hostenum, assemblyenum;
212                         
213                         hostenum = evidence.GetHostEnumerator ();
214                         while( hostenum.MoveNext () ) {
215                                 AddHost (hostenum.Current);
216                         }
217
218                         assemblyenum = evidence.GetAssemblyEnumerator ();
219                         while( assemblyenum.MoveNext () ) {
220                                 AddAssembly (assemblyenum.Current);
221                         }
222                 }
223
224 #if NET_2_0
225                 public void RemoveType (Type t)
226                 {
227                         for (int i = hostEvidenceList.Count; i >= 0; i--) {
228                                 if (hostEvidenceList.GetType () == t) {
229                                         hostEvidenceList.RemoveAt (i);
230                                         _hashCode = 0;
231                                 }
232                         }
233                         for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
234                                 if (assemblyEvidenceList.GetType () == t) {
235                                         assemblyEvidenceList.RemoveAt (i);
236                                         _hashCode = 0;
237                                 }
238                         }
239                 }
240 #endif
241
242                 // this avoid us to build all evidences from the runtime
243                 // (i.e. multiple unmanaged->managed calls) and also allows
244                 // to delay their creation until (if) needed
245                 static internal Evidence GetDefaultHostEvidence (Assembly a) 
246                 {
247                         Evidence e = new Evidence ();
248                         string aname = a.CodeBase;
249
250                         // by default all assembly have the Zone, Url and Hash evidences
251                         e.AddHost (Zone.CreateFromUrl (aname));
252                         e.AddHost (new Url (aname));
253                         e.AddHost (new Hash (a));
254
255                         // non local files (e.g. http://) also get a Site evidence
256                         if (!aname.ToUpper ().StartsWith ("FILE://")) {
257                                 e.AddHost (Site.CreateFromUrl (aname));
258                         }
259
260                         // strongnamed assemblies gets a StrongName evidence
261                         AssemblyName an = a.GetName ();
262                         byte[] pk = an.GetPublicKey ();
263                         if (pk != null) {
264                                 StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk);
265                                 e.AddHost (new StrongName (blob, an.Name, an.Version));
266                         }
267
268                         // Authenticode(r) signed assemblies get a Publisher evidence
269                         try {
270                                 X509Certificate x509 = X509Certificate.CreateFromSignedFile (a.Location);
271                                 if (x509.GetHashCode () != 0) {
272                                         e.AddHost (new Publisher (x509));
273                                 }
274                         }
275                         catch (ArgumentException) {
276                                 // URI are not supported
277                         }
278 #if NET_2_0
279                         // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
280                         if (a.GlobalAssemblyCache) {
281                                 e.AddHost (new Gac ());
282                         }
283 /*
284                         // the current HostSecurityManager may add/remove some evidence
285                         AppDomainManager dommgr = AppDomain.CurrentDomain.DomainManager;
286                         if (dommgr != null) {
287                                 if ((dommgr.HostSecurityManager.Flags & HostSecurityManagerFlags.HostAssemblyEvidence) ==
288                                         HostSecurityManagerFlags.HostAssemblyEvidence) {
289                                         e = dommgr.HostSecurityManager.ProvideAssemblyEvidence (a, e);
290                                 }
291                         }*/
292 #endif
293                         return e;
294                 }
295         
296                 private class EvidenceEnumerator : IEnumerator {
297                         
298                         private IEnumerator currentEnum, hostEnum, assemblyEnum;                
299         
300                         public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum) 
301                         {
302                                 this.hostEnum = hostenum;
303                                 this.assemblyEnum = assemblyenum;
304                                 currentEnum = hostEnum;                 
305                         }
306
307                         public bool MoveNext () 
308                         {
309                                 bool ret = currentEnum.MoveNext ();
310                                 
311                                 if ( !ret && hostEnum == currentEnum ) {
312                                         currentEnum = assemblyEnum;
313                                         ret = assemblyEnum.MoveNext ();
314                                 }
315
316                                 return ret;
317                         }
318
319                         public void Reset () 
320                         {
321                                 hostEnum.Reset ();
322                                 assemblyEnum.Reset ();
323                                 currentEnum = hostEnum;
324                         }
325
326                         public object Current {
327                                 get {
328                                         return currentEnum.Current;
329                                 }
330                         }
331                 }
332         }
333 }
334