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