Merge pull request #733 from amoiseev-softheme/bugfix/monofix
[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-2005 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.Globalization;
36 using System.Reflection;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 using System.Security.Permissions;
40 using System.Security.Cryptography.X509Certificates;
41 using Mono.Security.Authenticode;
42
43 namespace System.Security.Policy {
44
45         [Serializable]
46         [MonoTODO ("Serialization format not compatible with .NET")]
47         [ComVisible (true)]
48         public sealed class Evidence : ICollection, IEnumerable {
49         
50                 private bool _locked;
51                 private ArrayList hostEvidenceList;     
52                 private ArrayList assemblyEvidenceList;
53
54                 public Evidence () 
55                 {
56                 }
57
58                 public Evidence (Evidence evidence)
59                 {
60                         if (evidence != null)
61                                 Merge (evidence);       
62                 }
63
64 #if NET_4_0
65                 [Obsolete]
66 #endif
67                 public Evidence (object[] hostEvidence, object[] assemblyEvidence)
68                 {
69                         if (null != hostEvidence)
70                                 HostEvidenceList.AddRange (hostEvidence);
71                         if (null != assemblyEvidence)
72                                 AssemblyEvidenceList.AddRange (assemblyEvidence);
73                 }
74                 
75                 //
76                 // Public Properties
77                 //
78         
79 #if NET_4_0
80                 [Obsolete]
81 #endif
82                 public int Count {
83                         get {
84                                 int count = 0;
85                                 if (hostEvidenceList != null)
86                                         count += hostEvidenceList.Count;
87                                 if (assemblyEvidenceList!= null)
88                                         count += assemblyEvidenceList.Count;
89                                 return count;
90                         }
91                 }
92
93                 public bool IsReadOnly {
94                         get{ return false; }
95                 }
96                 
97                 public bool IsSynchronized {
98                         get { return false; }
99                 }
100
101                 public bool Locked {
102                         get { return _locked; }
103                         [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
104                         set { 
105                                 _locked = value; 
106                         }
107                 }       
108
109                 public object SyncRoot {
110                         get { return this; }
111                 }
112
113                 internal ArrayList HostEvidenceList {
114                         get {
115                                 if (hostEvidenceList == null)
116                                         hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
117                                 return hostEvidenceList;
118                         }
119                 }
120
121                 internal ArrayList AssemblyEvidenceList {
122                         get {
123                                 if (assemblyEvidenceList == null)
124                                         assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
125                                 return assemblyEvidenceList;
126                         }
127                 }
128
129                 //
130                 // Public Methods
131                 //
132
133 #if NET_4_0
134                 [Obsolete]
135 #endif
136                 public void AddAssembly (object id) 
137                 {
138                         AssemblyEvidenceList.Add (id);
139                 }
140
141 #if NET_4_0
142                 [Obsolete]
143 #endif
144                 public void AddHost (object id) 
145                 {
146                         if (_locked && SecurityManager.SecurityEnabled) {
147                                 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
148                         }
149                         HostEvidenceList.Add (id);
150                 }
151
152                 [ComVisible (false)]
153                 public void Clear ()
154                 {
155                         if (hostEvidenceList != null)
156                                 hostEvidenceList.Clear ();
157                         if (assemblyEvidenceList != null)
158                                 assemblyEvidenceList.Clear ();
159                 }
160
161 #if NET_4_0
162                 [Obsolete]
163 #endif
164                 public void CopyTo (Array array, int index) 
165                 {
166                         int hc = 0;
167                         if (hostEvidenceList != null) {
168                                 hc = hostEvidenceList.Count;
169                                 if (hc > 0)
170                                         hostEvidenceList.CopyTo (array, index);
171                         }
172                         if ((assemblyEvidenceList != null) && (assemblyEvidenceList.Count > 0))
173                                 assemblyEvidenceList.CopyTo (array, index + hc);
174                 }
175
176 #if !NET_4_0
177                 [ComVisible (false)]
178                 public override bool Equals (object obj)
179                 {
180                         if (obj == null)
181                                 return false;
182                         Evidence e = (obj as Evidence);
183                         if (e == null)
184                                 return false;
185
186                         if (HostEvidenceList.Count != e.HostEvidenceList.Count)
187                                 return false;
188                         if (AssemblyEvidenceList.Count != e.AssemblyEvidenceList.Count)
189                                 return false;
190
191                         for (int i = 0; i < hostEvidenceList.Count; i++) {
192                                 bool found = false;
193                                 for (int j = 0; j < e.hostEvidenceList.Count; i++) {
194                                         if (hostEvidenceList [i].Equals (e.hostEvidenceList [j])) {
195                                                 found = true;
196                                                 break;
197                                         }
198                                 }
199                                 if (!found)
200                                         return false;
201                         }
202                         for (int i = 0; i < assemblyEvidenceList.Count; i++) {
203                                 bool found = false;
204                                 for (int j = 0; j < e.assemblyEvidenceList.Count; i++) {
205                                         if (assemblyEvidenceList [i].Equals (e.assemblyEvidenceList [j])) {
206                                                 found = true;
207                                                 break;
208                                         }
209                                 }
210                                 if (!found)
211                                         return false;
212                         }
213                         
214                         return true;
215                 }
216 #endif
217
218 #if NET_4_0
219                 [Obsolete]
220 #endif
221                 public IEnumerator GetEnumerator () 
222                 {
223                         IEnumerator he = null;
224                         if (hostEvidenceList != null)
225                                 he = hostEvidenceList.GetEnumerator ();
226                         IEnumerator ae = null;
227                         if (assemblyEvidenceList != null)
228                                 ae = assemblyEvidenceList.GetEnumerator ();
229                         return new EvidenceEnumerator (he, ae);
230                 }
231
232                 public IEnumerator GetAssemblyEnumerator () 
233                 {
234                         return AssemblyEvidenceList.GetEnumerator ();
235                 }
236
237 #if !NET_4_0
238                 [ComVisible (false)]
239                 public override int GetHashCode ()
240                 {
241                         int _hashCode = 0;
242                         if (hostEvidenceList != null) {
243                                 for (int i = 0; i < hostEvidenceList.Count; i++)
244                                         _hashCode ^= hostEvidenceList [i].GetHashCode ();
245                         }
246                         if (assemblyEvidenceList != null) {
247                                 for (int i = 0; i < assemblyEvidenceList.Count; i++)
248                                         _hashCode ^= assemblyEvidenceList [i].GetHashCode ();
249                         }
250                         
251                         return _hashCode;
252                 }
253 #endif
254                 public IEnumerator GetHostEnumerator () 
255                 {
256                         return HostEvidenceList.GetEnumerator ();
257                 }
258
259                 public void Merge (Evidence evidence) 
260                 {
261                         if ((evidence != null) && (evidence.Count > 0)) {
262                                 if (evidence.hostEvidenceList != null) {
263                                         foreach (object o in evidence.hostEvidenceList)
264                                                 AddHost (o);
265                                 }
266                                 if (evidence.assemblyEvidenceList != null) {
267                                         foreach (object o in evidence.assemblyEvidenceList)
268                                                 AddAssembly (o);
269                                 }
270                         }
271                 }
272
273                 [ComVisible (false)]
274                 public void RemoveType (Type t)
275                 {
276                         for (int i = hostEvidenceList.Count; i >= 0; i--) {
277                                 if (hostEvidenceList.GetType () == t) {
278                                         hostEvidenceList.RemoveAt (i);
279                                 }
280                         }
281                         for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
282                                 if (assemblyEvidenceList.GetType () == t) {
283                                         assemblyEvidenceList.RemoveAt (i);
284                                 }
285                         }
286                 }
287
288                 // Use an icall to avoid multiple file i/o to detect the 
289                 // "possible" presence of an Authenticode signature
290                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
291                 static extern bool IsAuthenticodePresent (Assembly a);
292 #if NET_2_1
293                 static internal Evidence GetDefaultHostEvidence (Assembly a)
294                 {
295                         return new Evidence ();
296                 }
297 #else
298                 // this avoid us to build all evidences from the runtime
299                 // (i.e. multiple unmanaged->managed calls) and also allows
300                 // to delay their creation until (if) needed
301                 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
302                 static internal Evidence GetDefaultHostEvidence (Assembly a) 
303                 {
304                         Evidence e = new Evidence ();
305                         string aname = a.EscapedCodeBase;
306
307                         // by default all assembly have the Zone, Url and Hash evidences
308                         e.AddHost (Zone.CreateFromUrl (aname));
309                         e.AddHost (new Url (aname));
310                         e.AddHost (new Hash (a));
311
312                         // non local files (e.g. http://) also get a Site evidence
313                         if (String.Compare ("FILE://", 0, aname, 0, 7, true, CultureInfo.InvariantCulture) != 0) {
314                                 e.AddHost (Site.CreateFromUrl (aname));
315                         }
316
317                         // strongnamed assemblies gets a StrongName evidence
318                         AssemblyName an = a.UnprotectedGetName ();
319                         byte[] pk = an.GetPublicKey ();
320                         if ((pk != null) && (pk.Length > 0)) {
321                                 StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk);
322                                 e.AddHost (new StrongName (blob, an.Name, an.Version));
323                         }
324
325                         // Authenticode(r) signed assemblies get a Publisher evidence
326                         if (IsAuthenticodePresent (a)) {
327                                 // Note: The certificate is part of the evidences even if it is not trusted!
328                                 // so we can't call X509Certificate.CreateFromSignedFile
329                                 AuthenticodeDeformatter ad = new AuthenticodeDeformatter (a.Location);
330                                 if (ad.SigningCertificate != null) {
331                                         X509Certificate x509 = new X509Certificate (ad.SigningCertificate.RawData);
332                                         if (x509.GetHashCode () != 0) {
333                                                 e.AddHost (new Publisher (x509));
334                                         }
335                                 }
336                         }
337                         // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
338                         if (a.GlobalAssemblyCache) {
339                                 e.AddHost (new GacInstalled ());
340                         }
341
342                         // the current HostSecurityManager may add/remove some evidence
343                         AppDomainManager dommgr = AppDomain.CurrentDomain.DomainManager;
344                         if (dommgr != null) {
345                                 if ((dommgr.HostSecurityManager.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) ==
346                                         HostSecurityManagerOptions.HostAssemblyEvidence) {
347                                         e = dommgr.HostSecurityManager.ProvideAssemblyEvidence (a, e);
348                                 }
349                         }
350
351                         return e;
352                 }
353
354 #endif // NET_2_1
355
356                 private class EvidenceEnumerator : IEnumerator {
357                         
358                         private IEnumerator currentEnum, hostEnum, assemblyEnum;                
359         
360                         public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum) 
361                         {
362                                 this.hostEnum = hostenum;
363                                 this.assemblyEnum = assemblyenum;
364                                 currentEnum = hostEnum;         
365                         }
366
367                         public bool MoveNext () 
368                         {
369                                 if (currentEnum == null)
370                                         return false;
371
372                                 bool ret = currentEnum.MoveNext ();
373                                 
374                                 if (!ret && (hostEnum == currentEnum) && (assemblyEnum != null)) {
375                                         currentEnum = assemblyEnum;
376                                         ret = assemblyEnum.MoveNext ();
377                                 }
378
379                                 return ret;
380                         }
381
382                         public void Reset () 
383                         {
384                                 if (hostEnum != null) {
385                                         hostEnum.Reset ();
386                                         currentEnum = hostEnum;
387                                 } else {
388                                         currentEnum = assemblyEnum;
389                                 }
390                                 if (assemblyEnum != null)
391                                         assemblyEnum.Reset ();
392                         }
393
394                         public object Current {
395                                 get {
396                                         return currentEnum.Current;
397                                 }
398                         }
399                 }
400         }
401 }
402