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)
65 public Evidence (object[] hostEvidence, object[] assemblyEvidence)
67 if (null != hostEvidence)
68 HostEvidenceList.AddRange (hostEvidence);
69 if (null != assemblyEvidence)
70 AssemblyEvidenceList.AddRange (assemblyEvidence);
81 if (hostEvidenceList != null)
82 count += hostEvidenceList.Count;
83 if (assemblyEvidenceList!= null)
84 count += assemblyEvidenceList.Count;
89 public bool IsReadOnly {
93 public bool IsSynchronized {
98 get { return _locked; }
99 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
105 public object SyncRoot {
109 internal ArrayList HostEvidenceList {
111 if (hostEvidenceList == null)
112 hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
113 return hostEvidenceList;
117 internal ArrayList AssemblyEvidenceList {
119 if (assemblyEvidenceList == null)
120 assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
121 return assemblyEvidenceList;
130 public void AddAssembly (object id)
132 AssemblyEvidenceList.Add (id);
136 public void AddHost (object id)
138 if (_locked && SecurityManager.SecurityEnabled) {
139 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
141 HostEvidenceList.Add (id);
147 if (hostEvidenceList != null)
148 hostEvidenceList.Clear ();
149 if (assemblyEvidenceList != null)
150 assemblyEvidenceList.Clear ();
154 public Evidence Clone ()
156 return new Evidence(this);
160 public void CopyTo (Array array, int index)
163 if (hostEvidenceList != null) {
164 hc = hostEvidenceList.Count;
166 hostEvidenceList.CopyTo (array, index);
168 if ((assemblyEvidenceList != null) && (assemblyEvidenceList.Count > 0))
169 assemblyEvidenceList.CopyTo (array, index + hc);
174 public IEnumerator GetEnumerator ()
176 IEnumerator he = null;
177 if (hostEvidenceList != null)
178 he = hostEvidenceList.GetEnumerator ();
179 IEnumerator ae = null;
180 if (assemblyEvidenceList != null)
181 ae = assemblyEvidenceList.GetEnumerator ();
182 return new EvidenceEnumerator (he, ae);
185 public IEnumerator GetAssemblyEnumerator ()
187 return AssemblyEvidenceList.GetEnumerator ();
190 public IEnumerator GetHostEnumerator ()
192 return HostEvidenceList.GetEnumerator ();
195 public void Merge (Evidence evidence)
197 if ((evidence != null) && (evidence.Count > 0)) {
198 if (evidence.hostEvidenceList != null) {
199 foreach (object o in evidence.hostEvidenceList)
202 if (evidence.assemblyEvidenceList != null) {
203 foreach (object o in evidence.assemblyEvidenceList)
210 public void RemoveType (Type t)
212 for (int i = hostEvidenceList.Count; i >= 0; i--) {
213 if (hostEvidenceList.GetType () == t) {
214 hostEvidenceList.RemoveAt (i);
217 for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
218 if (assemblyEvidenceList.GetType () == t) {
219 assemblyEvidenceList.RemoveAt (i);
224 // Use an icall to avoid multiple file i/o to detect the
225 // "possible" presence of an Authenticode signature
226 [MethodImplAttribute (MethodImplOptions.InternalCall)]
227 static extern bool IsAuthenticodePresent (Assembly a);
229 static internal Evidence GetDefaultHostEvidence (Assembly a)
231 return new Evidence ();
234 // this avoid us to build all evidences from the runtime
235 // (i.e. multiple unmanaged->managed calls) and also allows
236 // to delay their creation until (if) needed
237 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
238 static internal Evidence GetDefaultHostEvidence (Assembly a)
240 Evidence e = new Evidence ();
241 string aname = a.EscapedCodeBase;
243 // by default all assembly have the Zone, Url and Hash evidences
244 e.AddHost (Zone.CreateFromUrl (aname));
245 e.AddHost (new Url (aname));
246 e.AddHost (new Hash (a));
248 // non local files (e.g. http://) also get a Site evidence
249 if (String.Compare ("FILE://", 0, aname, 0, 7, true, CultureInfo.InvariantCulture) != 0) {
250 e.AddHost (Site.CreateFromUrl (aname));
253 // strongnamed assemblies gets a StrongName evidence
254 AssemblyName an = a.GetName ();
255 byte[] pk = an.GetPublicKey ();
256 if ((pk != null) && (pk.Length > 0)) {
257 StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk);
258 e.AddHost (new StrongName (blob, an.Name, an.Version));
261 // Authenticode(r) signed assemblies get a Publisher evidence
262 if (IsAuthenticodePresent (a)) {
263 // Note: The certificate is part of the evidences even if it is not trusted!
264 // so we can't call X509Certificate.CreateFromSignedFile
265 AuthenticodeDeformatter ad = new AuthenticodeDeformatter (a.Location);
266 if (ad.SigningCertificate != null) {
267 X509Certificate x509 = new X509Certificate (ad.SigningCertificate.RawData);
268 if (x509.GetHashCode () != 0) {
269 e.AddHost (new Publisher (x509));
273 // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
274 if (a.GlobalAssemblyCache) {
275 e.AddHost (new GacInstalled ());
278 // the current HostSecurityManager may add/remove some evidence
279 AppDomainManager dommgr = AppDomain.CurrentDomain.DomainManager;
280 if (dommgr != null) {
281 if ((dommgr.HostSecurityManager.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) ==
282 HostSecurityManagerOptions.HostAssemblyEvidence) {
283 e = dommgr.HostSecurityManager.ProvideAssemblyEvidence (a, e);
292 private class EvidenceEnumerator : IEnumerator {
294 private IEnumerator currentEnum, hostEnum, assemblyEnum;
296 public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum)
298 this.hostEnum = hostenum;
299 this.assemblyEnum = assemblyenum;
300 currentEnum = hostEnum;
303 public bool MoveNext ()
305 if (currentEnum == null)
308 bool ret = currentEnum.MoveNext ();
310 if (!ret && (hostEnum == currentEnum) && (assemblyEnum != null)) {
311 currentEnum = assemblyEnum;
312 ret = assemblyEnum.MoveNext ();
320 if (hostEnum != null) {
322 currentEnum = hostEnum;
324 currentEnum = assemblyEnum;
326 if (assemblyEnum != null)
327 assemblyEnum.Reset ();
330 public object Current {
332 return currentEnum.Current;