2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Security.Policy / Evidence.cs
blob5d932f5259d0fec1b475152154acaa88b9129246
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)
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.
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;
42 #if !MOONLIGHT
43 using Mono.Security.Authenticode;
44 #endif
46 namespace System.Security.Policy {
48 [Serializable]
49 [MonoTODO ("Serialization format not compatible with .NET")]
50 [ComVisible (true)]
51 public sealed class Evidence : ICollection, IEnumerable {
53 private bool _locked;
54 private ArrayList hostEvidenceList;
55 private ArrayList assemblyEvidenceList;
56 private int _hashCode;
58 public Evidence ()
62 public Evidence (Evidence evidence)
64 if (evidence != null)
65 Merge (evidence);
68 #if NET_4_0
69 [Obsolete]
70 #endif
71 public Evidence (object[] hostEvidence, object[] assemblyEvidence)
73 if (null != hostEvidence)
74 HostEvidenceList.AddRange (hostEvidence);
75 if (null != assemblyEvidence)
76 AssemblyEvidenceList.AddRange (assemblyEvidence);
80 // Public Properties
83 #if NET_4_0
84 [Obsolete]
85 #endif
86 public int Count {
87 get {
88 int count = 0;
89 if (hostEvidenceList != null)
90 count += hostEvidenceList.Count;
91 if (assemblyEvidenceList!= null)
92 count += assemblyEvidenceList.Count;
93 return count;
97 public bool IsReadOnly {
98 get{ return false; }
101 public bool IsSynchronized {
102 get { return false; }
105 public bool Locked {
106 get { return _locked; }
107 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
108 set {
109 _locked = value;
113 public object SyncRoot {
114 get { return this; }
117 internal ArrayList HostEvidenceList {
118 get {
119 if (hostEvidenceList == null)
120 hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
121 return hostEvidenceList;
125 internal ArrayList AssemblyEvidenceList {
126 get {
127 if (assemblyEvidenceList == null)
128 assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
129 return assemblyEvidenceList;
134 // Public Methods
137 #if NET_4_0
138 [Obsolete]
139 #endif
140 public void AddAssembly (object id)
142 AssemblyEvidenceList.Add (id);
143 _hashCode = 0;
146 #if NET_4_0
147 [Obsolete]
148 #endif
149 public void AddHost (object id)
151 if (_locked && SecurityManager.SecurityEnabled) {
152 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
154 HostEvidenceList.Add (id);
155 _hashCode = 0;
158 [ComVisible (false)]
159 public void Clear ()
161 if (hostEvidenceList != null)
162 hostEvidenceList.Clear ();
163 if (assemblyEvidenceList != null)
164 assemblyEvidenceList.Clear ();
165 _hashCode = 0;
168 #if NET_4_0
169 [Obsolete]
170 #endif
171 public void CopyTo (Array array, int index)
173 int hc = 0;
174 if (hostEvidenceList != null) {
175 hc = hostEvidenceList.Count;
176 if (hc > 0)
177 hostEvidenceList.CopyTo (array, index);
179 if ((assemblyEvidenceList != null) && (assemblyEvidenceList.Count > 0))
180 assemblyEvidenceList.CopyTo (array, index + hc);
183 [ComVisible (false)]
184 public override bool Equals (object obj)
186 if (obj == null)
187 return false;
188 Evidence e = (obj as Evidence);
189 if (e == null)
190 return false;
192 if (HostEvidenceList.Count != e.HostEvidenceList.Count)
193 return false;
194 if (AssemblyEvidenceList.Count != e.AssemblyEvidenceList.Count)
195 return false;
197 for (int i = 0; i < hostEvidenceList.Count; i++) {
198 bool found = false;
199 for (int j = 0; j < e.hostEvidenceList.Count; i++) {
200 if (hostEvidenceList [i].Equals (e.hostEvidenceList [j])) {
201 found = true;
202 break;
205 if (!found)
206 return false;
208 for (int i = 0; i < assemblyEvidenceList.Count; i++) {
209 bool found = false;
210 for (int j = 0; j < e.assemblyEvidenceList.Count; i++) {
211 if (assemblyEvidenceList [i].Equals (e.assemblyEvidenceList [j])) {
212 found = true;
213 break;
216 if (!found)
217 return false;
220 return true;
223 #if NET_4_0
224 [Obsolete]
225 #endif
226 public IEnumerator GetEnumerator ()
228 IEnumerator he = null;
229 if (hostEvidenceList != null)
230 he = hostEvidenceList.GetEnumerator ();
231 IEnumerator ae = null;
232 if (assemblyEvidenceList != null)
233 ae = assemblyEvidenceList.GetEnumerator ();
234 return new EvidenceEnumerator (he, ae);
237 public IEnumerator GetAssemblyEnumerator ()
239 return AssemblyEvidenceList.GetEnumerator ();
242 [ComVisible (false)]
243 public override int GetHashCode ()
245 // kind of long so we cache it
246 if (_hashCode == 0) {
247 if (hostEvidenceList != null) {
248 for (int i = 0; i < hostEvidenceList.Count; i++)
249 _hashCode ^= hostEvidenceList [i].GetHashCode ();
251 if (assemblyEvidenceList != null) {
252 for (int i = 0; i < assemblyEvidenceList.Count; i++)
253 _hashCode ^= assemblyEvidenceList [i].GetHashCode ();
256 return _hashCode;
259 public IEnumerator GetHostEnumerator ()
261 return HostEvidenceList.GetEnumerator ();
264 public void Merge (Evidence evidence)
266 if ((evidence != null) && (evidence.Count > 0)) {
267 if (evidence.hostEvidenceList != null) {
268 foreach (object o in evidence.hostEvidenceList)
269 AddHost (o);
271 if (evidence.assemblyEvidenceList != null) {
272 foreach (object o in evidence.assemblyEvidenceList)
273 AddAssembly (o);
275 _hashCode = 0;
279 [ComVisible (false)]
280 public void RemoveType (Type t)
282 for (int i = hostEvidenceList.Count; i >= 0; i--) {
283 if (hostEvidenceList.GetType () == t) {
284 hostEvidenceList.RemoveAt (i);
285 _hashCode = 0;
288 for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
289 if (assemblyEvidenceList.GetType () == t) {
290 assemblyEvidenceList.RemoveAt (i);
291 _hashCode = 0;
296 // Use an icall to avoid multiple file i/o to detect the
297 // "possible" presence of an Authenticode signature
298 [MethodImplAttribute (MethodImplOptions.InternalCall)]
299 static extern bool IsAuthenticodePresent (Assembly a);
300 #if NET_2_1
301 static internal Evidence GetDefaultHostEvidence (Assembly a)
303 return new Evidence ();
305 #else
306 // this avoid us to build all evidences from the runtime
307 // (i.e. multiple unmanaged->managed calls) and also allows
308 // to delay their creation until (if) needed
309 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
310 static internal Evidence GetDefaultHostEvidence (Assembly a)
312 Evidence e = new Evidence ();
313 string aname = a.EscapedCodeBase;
315 // by default all assembly have the Zone, Url and Hash evidences
316 e.AddHost (Zone.CreateFromUrl (aname));
317 e.AddHost (new Url (aname));
318 e.AddHost (new Hash (a));
320 // non local files (e.g. http://) also get a Site evidence
321 if (String.Compare ("FILE://", 0, aname, 0, 7, true, CultureInfo.InvariantCulture) != 0) {
322 e.AddHost (Site.CreateFromUrl (aname));
325 // strongnamed assemblies gets a StrongName evidence
326 AssemblyName an = a.UnprotectedGetName ();
327 byte[] pk = an.GetPublicKey ();
328 if ((pk != null) && (pk.Length > 0)) {
329 StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk);
330 e.AddHost (new StrongName (blob, an.Name, an.Version));
333 // Authenticode(r) signed assemblies get a Publisher evidence
334 if (IsAuthenticodePresent (a)) {
335 // Note: The certificate is part of the evidences even if it is not trusted!
336 // so we can't call X509Certificate.CreateFromSignedFile
337 AuthenticodeDeformatter ad = new AuthenticodeDeformatter (a.Location);
338 if (ad.SigningCertificate != null) {
339 X509Certificate x509 = new X509Certificate (ad.SigningCertificate.RawData);
340 if (x509.GetHashCode () != 0) {
341 e.AddHost (new Publisher (x509));
345 // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
346 if (a.GlobalAssemblyCache) {
347 e.AddHost (new GacInstalled ());
350 // the current HostSecurityManager may add/remove some evidence
351 AppDomainManager dommgr = AppDomain.CurrentDomain.DomainManager;
352 if (dommgr != null) {
353 if ((dommgr.HostSecurityManager.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) ==
354 HostSecurityManagerOptions.HostAssemblyEvidence) {
355 e = dommgr.HostSecurityManager.ProvideAssemblyEvidence (a, e);
359 return e;
362 #endif // NET_2_1
364 private class EvidenceEnumerator : IEnumerator {
366 private IEnumerator currentEnum, hostEnum, assemblyEnum;
368 public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum)
370 this.hostEnum = hostenum;
371 this.assemblyEnum = assemblyenum;
372 currentEnum = hostEnum;
375 public bool MoveNext ()
377 if (currentEnum == null)
378 return false;
380 bool ret = currentEnum.MoveNext ();
382 if (!ret && (hostEnum == currentEnum) && (assemblyEnum != null)) {
383 currentEnum = assemblyEnum;
384 ret = assemblyEnum.MoveNext ();
387 return ret;
390 public void Reset ()
392 if (hostEnum != null) {
393 hostEnum.Reset ();
394 currentEnum = hostEnum;
395 } else {
396 currentEnum = assemblyEnum;
398 if (assemblyEnum != null)
399 assemblyEnum.Reset ();
402 public object Current {
403 get {
404 return currentEnum.Current;