2 // System.Security.Policy.Evidence
5 // Sean MacIsaac (macisaac@ximian.com)
6 // Nick Drochak (ndrochak@gol.com)
7 // Jackson Harper (Jackson@LatitudeGeo.com)
8 // Sebastien Pouliot <sebastien@ximian.com>
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:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
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;
41 using Mono.Security.Authenticode;
43 namespace System.Security.Policy {
46 [MonoTODO ("Serialization format not compatible with .NET")]
48 public sealed class Evidence : ICollection, IEnumerable {
51 private ArrayList hostEvidenceList;
52 private ArrayList assemblyEvidenceList;
58 public Evidence (Evidence evidence)
67 public Evidence (object[] hostEvidence, object[] assemblyEvidence)
69 if (null != hostEvidence)
70 HostEvidenceList.AddRange (hostEvidence);
71 if (null != assemblyEvidence)
72 AssemblyEvidenceList.AddRange (assemblyEvidence);
85 if (hostEvidenceList != null)
86 count += hostEvidenceList.Count;
87 if (assemblyEvidenceList!= null)
88 count += assemblyEvidenceList.Count;
93 public bool IsReadOnly {
97 public bool IsSynchronized {
102 get { return _locked; }
103 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
109 public object SyncRoot {
113 internal ArrayList HostEvidenceList {
115 if (hostEvidenceList == null)
116 hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
117 return hostEvidenceList;
121 internal ArrayList AssemblyEvidenceList {
123 if (assemblyEvidenceList == null)
124 assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
125 return assemblyEvidenceList;
136 public void AddAssembly (object id)
138 AssemblyEvidenceList.Add (id);
144 public void AddHost (object id)
146 if (_locked && SecurityManager.SecurityEnabled) {
147 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
149 HostEvidenceList.Add (id);
155 if (hostEvidenceList != null)
156 hostEvidenceList.Clear ();
157 if (assemblyEvidenceList != null)
158 assemblyEvidenceList.Clear ();
164 public void CopyTo (Array array, int index)
167 if (hostEvidenceList != null) {
168 hc = hostEvidenceList.Count;
170 hostEvidenceList.CopyTo (array, index);
172 if ((assemblyEvidenceList != null) && (assemblyEvidenceList.Count > 0))
173 assemblyEvidenceList.CopyTo (array, index + hc);
178 public override bool Equals (object obj)
182 Evidence e = (obj as Evidence);
186 if (HostEvidenceList.Count != e.HostEvidenceList.Count)
188 if (AssemblyEvidenceList.Count != e.AssemblyEvidenceList.Count)
191 for (int i = 0; i < hostEvidenceList.Count; i++) {
193 for (int j = 0; j < e.hostEvidenceList.Count; i++) {
194 if (hostEvidenceList [i].Equals (e.hostEvidenceList [j])) {
202 for (int i = 0; i < assemblyEvidenceList.Count; i++) {
204 for (int j = 0; j < e.assemblyEvidenceList.Count; i++) {
205 if (assemblyEvidenceList [i].Equals (e.assemblyEvidenceList [j])) {
221 public IEnumerator GetEnumerator ()
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);
232 public IEnumerator GetAssemblyEnumerator ()
234 return AssemblyEvidenceList.GetEnumerator ();
239 public override int GetHashCode ()
242 if (hostEvidenceList != null) {
243 for (int i = 0; i < hostEvidenceList.Count; i++)
244 _hashCode ^= hostEvidenceList [i].GetHashCode ();
246 if (assemblyEvidenceList != null) {
247 for (int i = 0; i < assemblyEvidenceList.Count; i++)
248 _hashCode ^= assemblyEvidenceList [i].GetHashCode ();
254 public IEnumerator GetHostEnumerator ()
256 return HostEvidenceList.GetEnumerator ();
259 public void Merge (Evidence evidence)
261 if ((evidence != null) && (evidence.Count > 0)) {
262 if (evidence.hostEvidenceList != null) {
263 foreach (object o in evidence.hostEvidenceList)
266 if (evidence.assemblyEvidenceList != null) {
267 foreach (object o in evidence.assemblyEvidenceList)
274 public void RemoveType (Type t)
276 for (int i = hostEvidenceList.Count; i >= 0; i--) {
277 if (hostEvidenceList.GetType () == t) {
278 hostEvidenceList.RemoveAt (i);
281 for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
282 if (assemblyEvidenceList.GetType () == t) {
283 assemblyEvidenceList.RemoveAt (i);
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);
293 static internal Evidence GetDefaultHostEvidence (Assembly a)
295 return new Evidence ();
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)
304 Evidence e = new Evidence ();
305 string aname = a.EscapedCodeBase;
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));
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));
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));
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));
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 ());
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);
356 private class EvidenceEnumerator : IEnumerator {
358 private IEnumerator currentEnum, hostEnum, assemblyEnum;
360 public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum)
362 this.hostEnum = hostenum;
363 this.assemblyEnum = assemblyenum;
364 currentEnum = hostEnum;
367 public bool MoveNext ()
369 if (currentEnum == null)
372 bool ret = currentEnum.MoveNext ();
374 if (!ret && (hostEnum == currentEnum) && (assemblyEnum != null)) {
375 currentEnum = assemblyEnum;
376 ret = assemblyEnum.MoveNext ();
384 if (hostEnum != null) {
386 currentEnum = hostEnum;
388 currentEnum = assemblyEnum;
390 if (assemblyEnum != null)
391 assemblyEnum.Reset ();
394 public object Current {
396 return currentEnum.Current;